From 2a1d8eeb81808d8cc922d355b54c6f053e545ce5 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Sat, 22 Aug 2009 13:59:06 +0200 Subject: update lemote support - add latest git changes from upstream - enable embedded controller driver for battery and fan control - add wireless driver support in patch - use sata/pata driver instead of ide support tested and verified via nfs boot on my lemote book --- target/lemote/Makefile | 2 +- target/lemote/kernel.config | 220 +- target/lemote/patches/yeelong.patch | 41116 ++++++++++++++++++++++++++++++---- 3 files changed, 37037 insertions(+), 4301 deletions(-) (limited to 'target/lemote') diff --git a/target/lemote/Makefile b/target/lemote/Makefile index 3893c35ba..4a4d4b78f 100644 --- a/target/lemote/Makefile +++ b/target/lemote/Makefile @@ -20,7 +20,7 @@ imageinstall: $(BIN_DIR)/$(ROOTFSTARBALL) @echo 'Boot your lemote and type following commands in PMON:' @echo 'PMON> ifaddr rtl0 ' @echo 'PMON> load tftp:///lemote-mips-kernel' - @echo 'PMON> g console=tty root=/dev/nfs ip=dhcp init=/init' + @echo 'PMON> g no_auto_cmd root=/dev/nfs ip=dhcp init=/init' endif ifeq ($(FS),initramfs) imageinstall: $(BIN_DIR)/$(INITRAMFS) diff --git a/target/lemote/kernel.config b/target/lemote/kernel.config index f51a5d828..a1fc83cc1 100644 --- a/target/lemote/kernel.config +++ b/target/lemote/kernel.config @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.30 -# Fri Jul 3 19:30:18 2009 +# Linux kernel version: 2.6.30.5 +# Sat Aug 22 13:14:36 2009 # CONFIG_MIPS=y @@ -143,10 +143,6 @@ CONFIG_SPARSEMEM_MANUAL=y CONFIG_SPARSEMEM=y CONFIG_HAVE_MEMORY_PRESENT=y CONFIG_SPARSEMEM_STATIC=y - -# -# Memory hotplug is currently incompatible with Software Suspend -# CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_PHYS_ADDR_T_64BIT=y @@ -155,6 +151,7 @@ CONFIG_VIRT_TO_BUS=y CONFIG_UNEVICTABLE_LRU=y CONFIG_HAVE_MLOCK=y CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_TICK_ONESHOT=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -185,6 +182,12 @@ CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_BZIP2=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -206,8 +209,7 @@ CONFIG_CLASSIC_RCU=y CONFIG_LOG_BUF_SHIFT=15 # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set @@ -224,7 +226,7 @@ CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_ELF_CORE is not set # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_BASE_FULL=y +# CONFIG_BASE_FULL is not set CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y @@ -246,7 +248,7 @@ CONFIG_HAVE_SYSCALL_WRAPPERS=y # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 +CONFIG_BASE_SMALL=1 CONFIG_MODULES=y # CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y @@ -279,7 +281,7 @@ CONFIG_HW_HAS_PCI=y CONFIG_PCI=y CONFIG_PCI_DOMAINS=y # CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y +# CONFIG_PCI_LEGACY is not set # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set CONFIG_ISA=y @@ -303,15 +305,12 @@ CONFIG_BINFMT_ELF32=y # # Power management options # -CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_PM=y # CONFIG_PM_DEBUG is not set CONFIG_PM_SLEEP=y CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y -CONFIG_HIBERNATION=y -CONFIG_PM_STD_PARTITION="" # # CPU Frequency scaling @@ -445,89 +444,17 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_HD is not set # CONFIG_MISC_DEVICES is not set CONFIG_HAVE_IDE=y -CONFIG_IDE=y - -# -# Please see Documentation/ide/ide.txt for help/info on IDE drives -# -CONFIG_IDE_XFER_MODE=y -CONFIG_IDE_TIMINGS=y -CONFIG_IDE_ATAPI=y -# CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_IDE_GD=y -CONFIG_IDE_GD_ATA=y -# CONFIG_IDE_GD_ATAPI is not set -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y -# CONFIG_BLK_DEV_IDETAPE is not set -CONFIG_IDE_TASK_IOCTL=y -# CONFIG_IDE_PROC_FS is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_IDE_GENERIC is not set -# CONFIG_BLK_DEV_PLATFORM is not set -# CONFIG_BLK_DEV_IDEPNP is not set -CONFIG_BLK_DEV_IDEDMA_SFF=y - -# -# PCI IDE chipsets support -# -CONFIG_BLK_DEV_IDEPCI=y -# CONFIG_IDEPCI_PCIBUS_ORDER is not set -# CONFIG_BLK_DEV_OFFBOARD is not set -CONFIG_BLK_DEV_GENERIC=y -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CS5520 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_JMICRON is not set -# CONFIG_BLK_DEV_SC1200 is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_IT8172 is not set -# CONFIG_BLK_DEV_IT8213 is not set -# CONFIG_BLK_DEV_IT821X is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_BLK_DEV_TC86C001 is not set - -# -# Other IDE chipsets support -# - -# -# Note: most of these also require special kernel boot parameters -# -# CONFIG_BLK_DEV_4DRIVES is not set -# CONFIG_BLK_DEV_ALI14XX is not set -# CONFIG_BLK_DEV_DTC2278 is not set -# CONFIG_BLK_DEV_HT6560B is not set -# CONFIG_BLK_DEV_QD65XX is not set -# CONFIG_BLK_DEV_UMC8672 is not set -CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDE is not set # # SCSI device support # -CONFIG_RAID_ATTRS=m +# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y # CONFIG_SCSI_TGT is not set -CONFIG_SCSI_NETLINK=y -CONFIG_SCSI_PROC_FS=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_PROC_FS is not set # # SCSI support type (disk, tape, CD-ROM) @@ -535,32 +462,94 @@ CONFIG_SCSI_PROC_FS=y CONFIG_BLK_DEV_SD=y # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_CHR_DEV_SG=m +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set # CONFIG_CHR_DEV_SCH is not set # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set # CONFIG_SCSI_SCAN_ASYNC is not set CONFIG_SCSI_WAIT_SCAN=m # # SCSI Transports # -CONFIG_SCSI_SPI_ATTRS=m -CONFIG_SCSI_FC_ATTRS=m -CONFIG_SCSI_ISCSI_ATTRS=m +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_LIBSAS is not set -CONFIG_SCSI_SRP_ATTRS=m +# CONFIG_SCSI_SRP_ATTRS is not set # CONFIG_SCSI_LOWLEVEL is not set # CONFIG_SCSI_DH is not set # CONFIG_SCSI_OSD_INITIATOR is not set -# CONFIG_ATA is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +# CONFIG_SATA_PMP is not set +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_SIL24 is not set +CONFIG_ATA_SFF=y +# CONFIG_SATA_SVW is not set +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SX4 is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_PATA_ALI is not set +CONFIG_PATA_AMD=y +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_ISAPNP is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_QDI is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set +# CONFIG_PATA_WINBOND_VLB is not set +# CONFIG_PATA_PLATFORM is not set +# CONFIG_PATA_SCH is not set # CONFIG_MD is not set # CONFIG_FUSION is not set @@ -686,7 +675,7 @@ CONFIG_INPUT=y CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600 # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -727,7 +716,7 @@ CONFIG_MOUSE_PS2=y CONFIG_SERIO=y CONFIG_SERIO_I8042=y # CONFIG_SERIO_SERPORT is not set -CONFIG_SERIO_PCIPS2=y +# CONFIG_SERIO_PCIPS2 is not set CONFIG_SERIO_LIBPS2=y # CONFIG_SERIO_RAW is not set # CONFIG_GAMEPORT is not set @@ -752,7 +741,7 @@ CONFIG_SERIAL_8250=y # CONFIG_SERIAL_8250_PCI is not set # CONFIG_SERIAL_8250_PNP is not set CONFIG_SERIAL_8250_NR_UARTS=16 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -1032,26 +1021,26 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set # CONFIG_STAGING is not set +CONFIG_LOONGSON_PLATFORM_DEVICES=y +CONFIG_EC_KB3310B=y +# CONFIG_EC_KB3310B_DEBUG is not set # # File systems # -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set -CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set -CONFIG_DNOTIFY=y -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y +CONFIG_FILE_LOCKING=y +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY is not set # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -1110,11 +1099,11 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_TRACE_IRQFLAGS_SUPPORT=y CONFIG_PRINTK_TIME=y -CONFIG_ENABLE_WARN_DEPRECATED=y -CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y -CONFIG_UNUSED_SYMBOLS=y +# CONFIG_UNUSED_SYMBOLS is not set # CONFIG_DEBUG_FS is not set # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set @@ -1142,8 +1131,7 @@ CONFIG_CMDLINE="" # # Security options # -CONFIG_KEYS=y -# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # CONFIG_SECURITYFS is not set # CONFIG_SECURITY_FILE_CAPABILITIES is not set diff --git a/target/lemote/patches/yeelong.patch b/target/lemote/patches/yeelong.patch index 7a88585b9..9fbc55b3f 100644 --- a/target/lemote/patches/yeelong.patch +++ b/target/lemote/patches/yeelong.patch @@ -1,6 +1,6 @@ -diff -Nur linux-2.6.30.orig/arch/mips/configs/fulong_defconfig linux-2.6.30/arch/mips/configs/fulong_defconfig ---- linux-2.6.30.orig/arch/mips/configs/fulong_defconfig 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/configs/fulong_defconfig 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/configs/fulong_defconfig linux-2.6.30.5/arch/mips/configs/fulong_defconfig +--- linux-2.6.30.5.orig/arch/mips/configs/fulong_defconfig 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/configs/fulong_defconfig 1970-01-01 01:00:00.000000000 +0100 @@ -1,1912 +0,0 @@ -# -# Automatically generated make config: don't edit @@ -1914,14 +1914,14 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fulong_defconfig linux-2.6.30/arch -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y -diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/arch/mips/configs/fuloong2e_defconfig ---- linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/configs/fuloong2e_defconfig 2009-06-14 20:25:19.000000000 +0200 -@@ -0,0 +1,2018 @@ +diff -Nur linux-2.6.30.5.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30.5/arch/mips/configs/fuloong2e_defconfig +--- linux-2.6.30.5.orig/arch/mips/configs/fuloong2e_defconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/configs/fuloong2e_defconfig 2009-08-21 21:17:59.000000000 +0200 +@@ -0,0 +1,1919 @@ +# +# Automatically generated make config: don't edit -+# Linux kernel version: 2.6.30-rc8 -+# Thu Jun 11 01:50:35 2009 ++# Linux kernel version: 2.6.31-rc1 ++# Tue Jun 30 15:37:31 2009 +# +CONFIG_MIPS=y + @@ -1929,6 +1929,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# Machine selection +# +# CONFIG_MACH_ALCHEMY is not set ++# CONFIG_AR7 is not set +# CONFIG_BASLER_EXCITE is not set +# CONFIG_BCM47XX is not set +# CONFIG_MIPS_COBALT is not set @@ -1965,6 +1966,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# CONFIG_WR_PPMC is not set +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set +# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set ++# CONFIG_ALCHEMY_GPIO_INDIRECT is not set +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_LEMOTE_FULOONG2E=y +# CONFIG_LEMOTE_FULOONG2F is not set @@ -1989,7 +1991,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_EARLY_PRINTK=y +CONFIG_SYS_HAS_EARLY_PRINTK=y -+# CONFIG_HOTPLUG_CPU is not set ++CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y +CONFIG_I8259=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_ISA_DMA=y @@ -2057,20 +2059,24 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_SELECT_MEMORY_MODEL=y -+CONFIG_FLATMEM_MANUAL=y ++# CONFIG_FLATMEM_MANUAL is not set +# CONFIG_DISCONTIGMEM_MANUAL is not set -+# CONFIG_SPARSEMEM_MANUAL is not set -+CONFIG_FLATMEM=y -+CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_SPARSEMEM_MANUAL=y ++CONFIG_SPARSEMEM=y ++CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_STATIC=y ++ ++# ++# Memory hotplug is currently incompatible with Software Suspend ++# +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y -+CONFIG_UNEVICTABLE_LRU=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y @@ -2092,6 +2098,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_CONSTRUCTORS=y + +# +# General setup @@ -2141,7 +2148,6 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set -+# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y @@ -2155,18 +2161,28 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y ++ ++# ++# Performance Counters ++# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y ++# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y -+# CONFIG_MARKERS is not set ++CONFIG_MARKERS=y +CONFIG_OPROFILE=m +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_SYSCALL_WRAPPERS=y ++ ++# ++# GCOV-based kernel profiling ++# ++# CONFIG_GCOV_KERNEL is not set +# CONFIG_SLOW_WORK is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y @@ -2236,8 +2252,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y ++CONFIG_HIBERNATION_NVS=y +CONFIG_HIBERNATION=y -+CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_STD_PARTITION="/dev/hda3" + +# +# CPU Frequency scaling @@ -2336,6 +2353,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m ++# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_IP_VS is not set + +# @@ -2375,6 +2393,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +CONFIG_PHONET=m ++# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +CONFIG_NET_CLS_ROUTE=y +# CONFIG_DCB is not set @@ -2395,7 +2414,11 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +# CONFIG_LIB80211 is not set -+# CONFIG_MAC80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++CONFIG_MAC80211_DEFAULT_PS_VALUE=0 +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +CONFIG_NET_9P=m @@ -2619,10 +2642,6 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set -+ -+# -+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -+# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set @@ -2650,13 +2669,16 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# + +# -+# Enable only one of the two stacks, unless you know what you are doing ++# You can enable one or both FireWire driver stacks. ++# ++ ++# ++# See the help texts for more information. +# +# CONFIG_FIREWIRE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y -+CONFIG_COMPAT_NET_DEV_OPS=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +CONFIG_MACVLAN=m @@ -2734,6 +2756,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# CONFIG_SMSC9420 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set ++# CONFIG_KS8842 is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_SC92031 is not set +# CONFIG_ATL2 is not set @@ -2755,6 +2778,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set ++# CONFIG_CNIC is not set +# CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set @@ -2867,6 +2891,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set @@ -2984,13 +3009,17 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set -+# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set ++ ++# ++# PPS support ++# ++# CONFIG_PPS is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set @@ -3014,143 +3043,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set ++# CONFIG_AB3100_CORE is not set +# CONFIG_REGULATOR is not set -+ -+# -+# Multimedia devices -+# -+ -+# -+# Multimedia core support -+# -+CONFIG_VIDEO_DEV=m -+CONFIG_VIDEO_V4L2_COMMON=m -+CONFIG_VIDEO_ALLOW_V4L1=y -+CONFIG_VIDEO_V4L1_COMPAT=y -+# CONFIG_DVB_CORE is not set -+CONFIG_VIDEO_MEDIA=m -+ -+# -+# Multimedia drivers -+# -+CONFIG_MEDIA_ATTACH=y -+CONFIG_MEDIA_TUNER=m -+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set -+CONFIG_MEDIA_TUNER_SIMPLE=m -+CONFIG_MEDIA_TUNER_TDA8290=m -+CONFIG_MEDIA_TUNER_TDA9887=m -+CONFIG_MEDIA_TUNER_TEA5761=m -+CONFIG_MEDIA_TUNER_TEA5767=m -+CONFIG_MEDIA_TUNER_MT20XX=m -+CONFIG_MEDIA_TUNER_XC2028=m -+CONFIG_MEDIA_TUNER_XC5000=m -+CONFIG_MEDIA_TUNER_MC44S803=m -+CONFIG_VIDEO_V4L2=m -+CONFIG_VIDEO_V4L1=m -+CONFIG_VIDEOBUF_GEN=m -+CONFIG_VIDEOBUF_VMALLOC=m -+CONFIG_VIDEO_CAPTURE_DRIVERS=y -+# CONFIG_VIDEO_ADV_DEBUG is not set -+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y -+# CONFIG_VIDEO_VIVI is not set -+# CONFIG_VIDEO_BT848 is not set -+# CONFIG_VIDEO_PMS is not set -+# CONFIG_VIDEO_CPIA is not set -+# CONFIG_VIDEO_CPIA2 is not set -+# CONFIG_VIDEO_SAA5246A is not set -+# CONFIG_VIDEO_SAA5249 is not set -+# CONFIG_VIDEO_STRADIS is not set -+# CONFIG_VIDEO_SAA7134 is not set -+# CONFIG_VIDEO_MXB is not set -+# CONFIG_VIDEO_HEXIUM_ORION is not set -+# CONFIG_VIDEO_HEXIUM_GEMINI is not set -+# CONFIG_VIDEO_CX88 is not set -+# CONFIG_VIDEO_IVTV is not set -+# CONFIG_VIDEO_CAFE_CCIC is not set -+CONFIG_SOC_CAMERA=m -+CONFIG_SOC_CAMERA_MT9M001=m -+CONFIG_SOC_CAMERA_MT9M111=m -+# CONFIG_SOC_CAMERA_MT9T031 is not set -+CONFIG_SOC_CAMERA_MT9V022=m -+# CONFIG_SOC_CAMERA_TW9910 is not set -+CONFIG_SOC_CAMERA_PLATFORM=m -+# CONFIG_SOC_CAMERA_OV772X is not set -+CONFIG_V4L_USB_DRIVERS=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -+CONFIG_USB_GSPCA=m -+CONFIG_USB_M5602=m -+# CONFIG_USB_STV06XX is not set -+CONFIG_USB_GSPCA_CONEX=m -+CONFIG_USB_GSPCA_ETOMS=m -+CONFIG_USB_GSPCA_FINEPIX=m -+CONFIG_USB_GSPCA_MARS=m -+# CONFIG_USB_GSPCA_MR97310A is not set -+CONFIG_USB_GSPCA_OV519=m -+# CONFIG_USB_GSPCA_OV534 is not set -+CONFIG_USB_GSPCA_PAC207=m -+CONFIG_USB_GSPCA_PAC7311=m -+CONFIG_USB_GSPCA_SONIXB=m -+CONFIG_USB_GSPCA_SONIXJ=m -+CONFIG_USB_GSPCA_SPCA500=m -+CONFIG_USB_GSPCA_SPCA501=m -+CONFIG_USB_GSPCA_SPCA505=m -+CONFIG_USB_GSPCA_SPCA506=m -+CONFIG_USB_GSPCA_SPCA508=m -+CONFIG_USB_GSPCA_SPCA561=m -+# CONFIG_USB_GSPCA_SQ905 is not set -+# CONFIG_USB_GSPCA_SQ905C is not set -+CONFIG_USB_GSPCA_STK014=m -+CONFIG_USB_GSPCA_SUNPLUS=m -+CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TV8532=m -+CONFIG_USB_GSPCA_VC032X=m -+CONFIG_USB_GSPCA_ZC3XX=m -+# CONFIG_VIDEO_PVRUSB2 is not set -+# CONFIG_VIDEO_HDPVR is not set -+# CONFIG_VIDEO_EM28XX is not set -+# CONFIG_VIDEO_CX231XX is not set -+# CONFIG_VIDEO_USBVISION is not set -+CONFIG_VIDEO_USBVIDEO=m -+CONFIG_USB_VICAM=m -+CONFIG_USB_IBMCAM=m -+CONFIG_USB_KONICAWC=m -+CONFIG_USB_QUICKCAM_MESSENGER=m -+CONFIG_USB_ET61X251=m -+# CONFIG_VIDEO_OVCAMCHIP is not set -+CONFIG_USB_OV511=m -+CONFIG_USB_SE401=m -+CONFIG_USB_SN9C102=m -+CONFIG_USB_STV680=m -+CONFIG_USB_ZC0301=m -+CONFIG_USB_PWC=m -+# CONFIG_USB_PWC_DEBUG is not set -+CONFIG_USB_PWC_INPUT_EVDEV=y -+# CONFIG_USB_ZR364XX is not set -+CONFIG_USB_STKWEBCAM=m -+CONFIG_USB_S2255=m -+CONFIG_RADIO_ADAPTERS=y -+# CONFIG_RADIO_CADET is not set -+# CONFIG_RADIO_RTRACK is not set -+# CONFIG_RADIO_RTRACK2 is not set -+# CONFIG_RADIO_AZTECH is not set -+# CONFIG_RADIO_GEMTEK is not set -+# CONFIG_RADIO_GEMTEK_PCI is not set -+# CONFIG_RADIO_MAXIRADIO is not set -+# CONFIG_RADIO_MAESTRO is not set -+# CONFIG_RADIO_SF16FMI is not set -+# CONFIG_RADIO_SF16FMR2 is not set -+# CONFIG_RADIO_TERRATEC is not set -+# CONFIG_RADIO_TRUST is not set -+# CONFIG_RADIO_TYPHOON is not set -+# CONFIG_RADIO_ZOLTRIX is not set -+# CONFIG_USB_DSBR is not set -+CONFIG_USB_SI470X=m -+CONFIG_USB_MR800=m -+# CONFIG_RADIO_TEA5764 is not set -+CONFIG_DAB=y -+# CONFIG_USB_DABUSB is not set ++# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support @@ -3258,6 +3153,11 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_VMASTER=y ++CONFIG_SND_RAWMIDI_SEQ=m ++# CONFIG_SND_OPL3_LIB_SEQ is not set ++# CONFIG_SND_OPL4_LIB_SEQ is not set ++# CONFIG_SND_SBAWE_SEQ is not set ++# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_MPU401_UART=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_DRIVERS=y @@ -3285,6 +3185,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CS5535AUDIO is not set ++# CONFIG_SND_CTXFI is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set @@ -3315,6 +3216,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set ++# CONFIG_SND_LX6464ES is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set @@ -3364,7 +3266,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m -+# CONFIG_DRAGONRISE_FF is not set ++# CONFIG_HID_DRAGONRISE is not set +CONFIG_HID_EZKEY=m +# CONFIG_HID_KYE is not set +CONFIG_HID_GYRATION=m @@ -3381,10 +3283,11 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SUNPLUS=m -+# CONFIG_GREENASIA_FF is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TOPSEED is not set -+# CONFIG_THRUSTMASTER_FF is not set -+CONFIG_ZEROPLUS_FF=m ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_ZEROPLUS is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y @@ -3412,6 +3315,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# USB Host Controller Drivers +# +CONFIG_USB_C67X00_HCD=m ++# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y @@ -3536,6 +3440,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set ++# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers @@ -3568,6 +3473,10 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# CONFIG_UIO_SMX is not set +# CONFIG_UIO_AEC is not set +# CONFIG_UIO_SERCOS3 is not set ++ ++# ++# TI VLYNQ ++# +# CONFIG_STAGING is not set + +# @@ -3596,11 +3505,12 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +# CONFIG_REISERFS_FS_XATTR is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y -+CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set ++CONFIG_FILE_LOCKING=y ++CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y @@ -3608,6 +3518,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y ++# CONFIG_CUSE is not set + +# +# Caches @@ -3672,6 +3583,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y ++# CONFIG_NFS_V4_1 is not set +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y @@ -3784,22 +3696,11 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_NOP_TRACER=y +CONFIG_RING_BUFFER=y ++CONFIG_EVENT_TRACING=y ++CONFIG_CONTEXT_SWITCH_TRACER=y +CONFIG_TRACING=y +CONFIG_TRACING_SUPPORT=y -+ -+# -+# Tracers -+# -+# CONFIG_IRQSOFF_TRACER is not set -+# CONFIG_SCHED_TRACER is not set -+# CONFIG_CONTEXT_SWITCH_TRACER is not set -+# CONFIG_EVENT_TRACER is not set -+# CONFIG_BOOT_TRACER is not set -+# CONFIG_TRACE_BRANCH_PROFILING is not set -+# CONFIG_KMEMTRACE is not set -+# CONFIG_WORKQUEUE_TRACER is not set -+# CONFIG_BLK_DEV_IO_TRACE is not set -+# CONFIG_FTRACE_STARTUP_TEST is not set ++# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y @@ -3936,9 +3837,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2e_defconfig linux-2.6.30/a +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y -diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2f_defconfig linux-2.6.30/arch/mips/configs/fuloong2f_defconfig ---- linux-2.6.30.orig/arch/mips/configs/fuloong2f_defconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/configs/fuloong2f_defconfig 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/configs/fuloong2f_defconfig linux-2.6.30.5/arch/mips/configs/fuloong2f_defconfig +--- linux-2.6.30.5.orig/arch/mips/configs/fuloong2f_defconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/configs/fuloong2f_defconfig 2009-08-21 21:17:59.000000000 +0200 @@ -0,0 +1,2637 @@ +# +# Automatically generated make config: don't edit @@ -6577,14 +6478,14 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/fuloong2f_defconfig linux-2.6.30/a +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y -diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/arch/mips/configs/yeeloong2f_defconfig ---- linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/configs/yeeloong2f_defconfig 2009-06-14 20:25:19.000000000 +0200 -@@ -0,0 +1,2711 @@ +diff -Nur linux-2.6.30.5.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30.5/arch/mips/configs/yeeloong2f_defconfig +--- linux-2.6.30.5.orig/arch/mips/configs/yeeloong2f_defconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/configs/yeeloong2f_defconfig 2009-08-21 21:17:59.000000000 +0200 +@@ -0,0 +1,2591 @@ +# +# Automatically generated make config: don't edit -+# Linux kernel version: 2.6.30-rc8 -+# Wed Jun 10 22:18:32 2009 ++# Linux kernel version: 2.6.31-rc2 ++# Sat Jul 11 00:34:44 2009 +# +CONFIG_MIPS=y + @@ -6592,6 +6493,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# Machine selection +# +# CONFIG_MACH_ALCHEMY is not set ++# CONFIG_AR7 is not set +# CONFIG_BASLER_EXCITE is not set +# CONFIG_BCM47XX is not set +# CONFIG_MIPS_COBALT is not set @@ -6628,6 +6530,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_WR_PPMC is not set +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set +# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set ++# CONFIG_ALCHEMY_GPIO_INDIRECT is not set +CONFIG_ARCH_SPARSEMEM_ENABLE=y +# CONFIG_LEMOTE_FULOONG2E is not set +# CONFIG_LEMOTE_FULOONG2F is not set @@ -6652,7 +6555,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_EARLY_PRINTK=y +CONFIG_SYS_HAS_EARLY_PRINTK=y -+# CONFIG_HOTPLUG_CPU is not set ++CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y +CONFIG_I8259=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_ISA_DMA=y @@ -6735,9 +6638,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y -+CONFIG_UNEVICTABLE_LRU=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y @@ -6759,6 +6662,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_CONSTRUCTORS=y + +# +# General setup @@ -6807,7 +6711,6 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set -+# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y @@ -6821,18 +6724,28 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y ++ ++# ++# Performance Counters ++# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y ++# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y -+# CONFIG_MARKERS is not set ++CONFIG_MARKERS=y +CONFIG_OPROFILE=m +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_SYSCALL_WRAPPERS=y ++ ++# ++# GCOV-based kernel profiling ++# ++# CONFIG_GCOV_KERNEL is not set +# CONFIG_SLOW_WORK is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y @@ -6906,8 +6819,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y ++CONFIG_HIBERNATION_NVS=y +CONFIG_HIBERNATION=y -+CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_STD_PARTITION="/dev/hda3" + +# +# CPU Frequency scaling @@ -7067,6 +6981,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set ++# CONFIG_NETFILTER_XT_MATCH_OSF is not set +CONFIG_IP_VS=m +# CONFIG_IP_VS_IPV6 is not set +# CONFIG_IP_VS_DEBUG is not set @@ -7227,6 +7142,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_ECONET_NATIVE=y +CONFIG_WAN_ROUTER=m +# CONFIG_PHONET is not set ++# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# @@ -7390,11 +7306,14 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_WIRELESS=y +CONFIG_CFG80211=y +# CONFIG_CFG80211_REG_DEBUG is not set ++# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_WIRELESS_OLD_REGULATORY=y +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +# CONFIG_LIB80211 is not set +CONFIG_MAC80211=y ++CONFIG_MAC80211_DEFAULT_PS=y ++CONFIG_MAC80211_DEFAULT_PS_VALUE=1 + +# +# Rate control algorithm selection @@ -7573,7 +7492,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set ++# CONFIG_EEPROM_MAX6875 is not set +CONFIG_EEPROM_93CX6=y ++# CONFIG_CB710_CORE is not set +CONFIG_HAVE_IDE=y +CONFIG_IDE=y + @@ -7669,10 +7590,6 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set -+ -+# -+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -+# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y @@ -7706,8 +7623,11 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m ++# CONFIG_DM_LOG_USERSPACE is not set +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m ++# CONFIG_DM_MULTIPATH_QL is not set ++# CONFIG_DM_MULTIPATH_ST is not set +# CONFIG_DM_DELAY is not set +# CONFIG_DM_UEVENT is not set +# CONFIG_FUSION is not set @@ -7717,13 +7637,16 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# + +# -+# Enable only one of the two stacks, unless you know what you are doing ++# You can enable one or both FireWire driver stacks. ++# ++ ++# ++# See the help texts for more information. +# +# CONFIG_FIREWIRE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y -+CONFIG_COMPAT_NET_DEV_OPS=y +CONFIG_IFB=m +CONFIG_DUMMY=m +# CONFIG_BONDING is not set @@ -7804,6 +7727,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_SMSC9420 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set ++# CONFIG_KS8842 is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_SC92031 is not set +# CONFIG_ATL2 is not set @@ -7824,7 +7748,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8180 is not set -+CONFIG_RTL8187=y ++CONFIG_RTL8187B=y +# CONFIG_ADM8211 is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_MWL8K is not set @@ -7841,6 +7765,8 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_ZD1211RW is not set +# CONFIG_RT2X00 is not set +# CONFIG_HERMES is not set ++# CONFIG_WL12XX is not set ++# CONFIG_IWM is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers @@ -7872,6 +7798,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_USB_EPSON2888=y +# CONFIG_USB_KC2190 is not set +CONFIG_USB_NET_ZAURUS=m ++# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_WAN is not set +# CONFIG_ATM_DRIVERS is not set +# CONFIG_FDDI is not set @@ -7926,6 +7853,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_KEYBOARD_XTKBD=m +CONFIG_KEYBOARD_NEWTON=m +# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_LM8323 is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y @@ -7942,6 +7870,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_MOUSE_LOGIBM=m +CONFIG_MOUSE_PC110PAD=m +CONFIG_MOUSE_VSXXXAA=m ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set @@ -8107,7 +8036,6 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_SENSORS_PCF8574=m +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set -+CONFIG_SENSORS_MAX6875=m +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set @@ -8126,6 +8054,11 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set ++ ++# ++# PPS support ++# ++# CONFIG_PPS is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set @@ -8174,174 +8107,10 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set ++# CONFIG_AB3100_CORE is not set ++# CONFIG_EZX_PCAP is not set +# CONFIG_REGULATOR is not set -+ -+# -+# Multimedia devices -+# -+ -+# -+# Multimedia core support -+# -+CONFIG_VIDEO_DEV=m -+CONFIG_VIDEO_V4L2_COMMON=m -+CONFIG_VIDEO_ALLOW_V4L1=y -+CONFIG_VIDEO_V4L1_COMPAT=y -+# CONFIG_DVB_CORE is not set -+CONFIG_VIDEO_MEDIA=m -+ -+# -+# Multimedia drivers -+# -+CONFIG_MEDIA_ATTACH=y -+CONFIG_MEDIA_TUNER=m -+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set -+CONFIG_MEDIA_TUNER_SIMPLE=m -+CONFIG_MEDIA_TUNER_TDA8290=m -+CONFIG_MEDIA_TUNER_TDA9887=m -+CONFIG_MEDIA_TUNER_TEA5761=m -+CONFIG_MEDIA_TUNER_TEA5767=m -+CONFIG_MEDIA_TUNER_MT20XX=m -+CONFIG_MEDIA_TUNER_XC2028=m -+CONFIG_MEDIA_TUNER_XC5000=m -+CONFIG_MEDIA_TUNER_MC44S803=m -+CONFIG_VIDEO_V4L2=m -+CONFIG_VIDEO_V4L1=m -+CONFIG_VIDEO_CAPTURE_DRIVERS=y -+# CONFIG_VIDEO_ADV_DEBUG is not set -+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set -+ -+# -+# Encoders/decoders and other helper chips -+# -+ -+# -+# Audio decoders -+# -+# CONFIG_VIDEO_TVAUDIO is not set -+# CONFIG_VIDEO_TDA7432 is not set -+# CONFIG_VIDEO_TDA9840 is not set -+# CONFIG_VIDEO_TDA9875 is not set -+# CONFIG_VIDEO_TEA6415C is not set -+# CONFIG_VIDEO_TEA6420 is not set -+# CONFIG_VIDEO_MSP3400 is not set -+# CONFIG_VIDEO_CS5345 is not set -+# CONFIG_VIDEO_CS53L32A is not set -+# CONFIG_VIDEO_M52790 is not set -+# CONFIG_VIDEO_TLV320AIC23B is not set -+# CONFIG_VIDEO_WM8775 is not set -+# CONFIG_VIDEO_WM8739 is not set -+# CONFIG_VIDEO_VP27SMPX is not set -+ -+# -+# RDS decoders -+# -+# CONFIG_VIDEO_SAA6588 is not set -+ -+# -+# Video decoders -+# -+# CONFIG_VIDEO_BT819 is not set -+# CONFIG_VIDEO_BT856 is not set -+# CONFIG_VIDEO_BT866 is not set -+# CONFIG_VIDEO_KS0127 is not set -+# CONFIG_VIDEO_OV7670 is not set -+# CONFIG_VIDEO_TCM825X is not set -+# CONFIG_VIDEO_SAA7110 is not set -+# CONFIG_VIDEO_SAA711X is not set -+# CONFIG_VIDEO_SAA717X is not set -+# CONFIG_VIDEO_SAA7191 is not set -+# CONFIG_VIDEO_TVP514X is not set -+# CONFIG_VIDEO_TVP5150 is not set -+# CONFIG_VIDEO_VPX3220 is not set -+ -+# -+# Video and audio decoders -+# -+# CONFIG_VIDEO_CX25840 is not set -+ -+# -+# MPEG video encoders -+# -+# CONFIG_VIDEO_CX2341X is not set -+ -+# -+# Video encoders -+# -+# CONFIG_VIDEO_SAA7127 is not set -+# CONFIG_VIDEO_SAA7185 is not set -+# CONFIG_VIDEO_ADV7170 is not set -+# CONFIG_VIDEO_ADV7175 is not set -+ -+# -+# Video improvement chips -+# -+# CONFIG_VIDEO_UPD64031A is not set -+# CONFIG_VIDEO_UPD64083 is not set -+# CONFIG_VIDEO_VIVI is not set -+# CONFIG_VIDEO_BT848 is not set -+# CONFIG_VIDEO_PMS is not set -+# CONFIG_VIDEO_CPIA is not set -+# CONFIG_VIDEO_CPIA2 is not set -+# CONFIG_VIDEO_SAA5246A is not set -+# CONFIG_VIDEO_SAA5249 is not set -+# CONFIG_VIDEO_STRADIS is not set -+# CONFIG_VIDEO_ZORAN is not set -+# CONFIG_VIDEO_SAA7134 is not set -+# CONFIG_VIDEO_MXB is not set -+# CONFIG_VIDEO_HEXIUM_ORION is not set -+# CONFIG_VIDEO_HEXIUM_GEMINI is not set -+# CONFIG_VIDEO_CX88 is not set -+# CONFIG_VIDEO_IVTV is not set -+# CONFIG_VIDEO_CAFE_CCIC is not set -+# CONFIG_SOC_CAMERA is not set -+CONFIG_V4L_USB_DRIVERS=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -+# CONFIG_USB_GSPCA is not set -+# CONFIG_VIDEO_PVRUSB2 is not set -+# CONFIG_VIDEO_HDPVR is not set -+# CONFIG_VIDEO_EM28XX is not set -+# CONFIG_VIDEO_CX231XX is not set -+# CONFIG_VIDEO_USBVISION is not set -+# CONFIG_USB_VICAM is not set -+# CONFIG_USB_IBMCAM is not set -+# CONFIG_USB_KONICAWC is not set -+# CONFIG_USB_QUICKCAM_MESSENGER is not set -+# CONFIG_USB_ET61X251 is not set -+# CONFIG_VIDEO_OVCAMCHIP is not set -+# CONFIG_USB_OV511 is not set -+# CONFIG_USB_SE401 is not set -+# CONFIG_USB_SN9C102 is not set -+# CONFIG_USB_STV680 is not set -+# CONFIG_USB_ZC0301 is not set -+# CONFIG_USB_PWC is not set -+CONFIG_USB_PWC_INPUT_EVDEV=y -+# CONFIG_USB_ZR364XX is not set -+# CONFIG_USB_STKWEBCAM is not set -+# CONFIG_USB_S2255 is not set -+CONFIG_RADIO_ADAPTERS=y -+CONFIG_RADIO_CADET=m -+CONFIG_RADIO_RTRACK=m -+CONFIG_RADIO_RTRACK2=m -+CONFIG_RADIO_AZTECH=m -+CONFIG_RADIO_GEMTEK=m -+CONFIG_RADIO_GEMTEK_PCI=m -+CONFIG_RADIO_MAXIRADIO=m -+CONFIG_RADIO_MAESTRO=m -+CONFIG_RADIO_SF16FMI=m -+CONFIG_RADIO_SF16FMR2=m -+CONFIG_RADIO_TERRATEC=m -+CONFIG_RADIO_TRUST=m -+CONFIG_RADIO_TYPHOON=m -+CONFIG_RADIO_TYPHOON_PROC_FS=y -+CONFIG_RADIO_ZOLTRIX=m -+CONFIG_USB_DSBR=m -+# CONFIG_USB_SI470X is not set -+# CONFIG_USB_MR800 is not set -+# CONFIG_RADIO_TEA5764 is not set -+# CONFIG_DAB is not set ++# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support @@ -8453,6 +8222,11 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_VMASTER=y ++CONFIG_SND_RAWMIDI_SEQ=m ++# CONFIG_SND_OPL3_LIB_SEQ is not set ++# CONFIG_SND_OPL4_LIB_SEQ is not set ++# CONFIG_SND_SBAWE_SEQ is not set ++# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_AC97_CODEC=y +CONFIG_SND_DRIVERS=y +CONFIG_SND_DUMMY=m @@ -8479,6 +8253,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +CONFIG_SND_CS5535AUDIO=y ++# CONFIG_SND_CTXFI is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set @@ -8509,6 +8284,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set ++# CONFIG_SND_LX6464ES is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set @@ -8551,7 +8327,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set -+# CONFIG_DRAGONRISE_FF is not set ++# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_GYRATION is not set @@ -8565,10 +8341,12 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SUNPLUS is not set -+# CONFIG_GREENASIA_FF is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TOPSEED is not set -+# CONFIG_THRUSTMASTER_FF is not set -+# CONFIG_ZEROPLUS_FF is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_ZEROPLUS is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y @@ -8595,6 +8373,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set ++# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set @@ -8753,6 +8532,8 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_SPI is not set ++# CONFIG_MMC_CB710 is not set ++# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=m @@ -8761,7 +8542,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set -+# CONFIG_LEDS_LP5521 is not set ++# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set @@ -8812,6 +8593,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set ++# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers @@ -8845,7 +8627,15 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set ++ ++# ++# TI VLYNQ ++# +# CONFIG_STAGING is not set ++CONFIG_LOONGSON_PLATFORM_DEVICES=y ++CONFIG_EC_KB3310B=y ++# CONFIG_EC_KB3310B_DEBUG is not set ++CONFIG_PMON_FLASH=m + +# +# File systems @@ -8882,7 +8672,6 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y -+CONFIG_FILE_LOCKING=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y @@ -8896,6 +8685,8 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_OCFS2_DEBUG_FS is not set +# CONFIG_OCFS2_FS_POSIX_ACL is not set +# CONFIG_BTRFS_FS is not set ++CONFIG_FILE_LOCKING=y ++CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y @@ -8909,6 +8700,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m ++# CONFIG_CUSE is not set + +# +# Caches @@ -8994,6 +8786,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y ++# CONFIG_NFS_V4_1 is not set +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y @@ -9120,22 +8913,11 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_NOP_TRACER=y +CONFIG_RING_BUFFER=y ++CONFIG_EVENT_TRACING=y ++CONFIG_CONTEXT_SWITCH_TRACER=y +CONFIG_TRACING=y +CONFIG_TRACING_SUPPORT=y -+ -+# -+# Tracers -+# -+# CONFIG_IRQSOFF_TRACER is not set -+# CONFIG_SCHED_TRACER is not set -+# CONFIG_CONTEXT_SWITCH_TRACER is not set -+# CONFIG_EVENT_TRACER is not set -+# CONFIG_BOOT_TRACER is not set -+# CONFIG_TRACE_BRANCH_PROFILING is not set -+# CONFIG_KMEMTRACE is not set -+# CONFIG_WORKQUEUE_TRACER is not set -+# CONFIG_BLK_DEV_IO_TRACE is not set -+# CONFIG_FTRACE_STARTUP_TEST is not set ++# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y @@ -9153,7 +8935,6 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +# CONFIG_SECURITY_PATH is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_SECURITY_ROOTPLUG is not set -+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0 +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 @@ -9292,9 +9073,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/configs/yeeloong2f_defconfig linux-2.6.30/ +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/bootinfo.h linux-2.6.30/arch/mips/include/asm/bootinfo.h ---- linux-2.6.30.orig/arch/mips/include/asm/bootinfo.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/bootinfo.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/bootinfo.h linux-2.6.30.5/arch/mips/include/asm/bootinfo.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/bootinfo.h 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/include/asm/bootinfo.h 2009-08-21 21:17:59.000000000 +0200 @@ -7,6 +7,7 @@ * Copyright (C) 1995, 1996 Andreas Busse * Copyright (C) 1995, 1996 Stoned Elipot @@ -9320,9 +9101,21 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/bootinfo.h linux-2.6.30/arch/m #define CL_SIZE COMMAND_LINE_SIZE extern char *system_type; -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/cpu-feature-overrides.h linux-2.6.30/arch/mips/include/asm/mach-lemote/cpu-feature-overrides.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/cpu-feature-overrides.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/mach-lemote/cpu-feature-overrides.h 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/bug.h linux-2.6.30.5/arch/mips/include/asm/bug.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/bug.h 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/include/asm/bug.h 2009-08-21 21:17:59.000000000 +0200 +@@ -5,6 +5,8 @@ + + #ifdef CONFIG_BUG + ++#include ++ + #include + + static inline void __noreturn BUG(void) +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-lemote/cpu-feature-overrides.h linux-2.6.30.5/arch/mips/include/asm/mach-lemote/cpu-feature-overrides.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-lemote/cpu-feature-overrides.h 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-lemote/cpu-feature-overrides.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,59 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public @@ -9383,79 +9176,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/cpu-feature-overri -#define cpu_icache_snoops_remote_store 1 - -#endif /* __ASM_MACH_LEMOTE_CPU_FEATURE_OVERRIDES_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/dma-coherence.h linux-2.6.30/arch/mips/include/asm/mach-lemote/dma-coherence.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/dma-coherence.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/mach-lemote/dma-coherence.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,66 +0,0 @@ --/* -- * This file is subject to the terms and conditions of the GNU General Public -- * License. See the file "COPYING" in the main directory of this archive -- * for more details. -- * -- * Copyright (C) 2006, 07 Ralf Baechle -- * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology -- * Author: Fuxin Zhang, zhangfx@lemote.com -- * -- */ --#ifndef __ASM_MACH_LEMOTE_DMA_COHERENCE_H --#define __ASM_MACH_LEMOTE_DMA_COHERENCE_H -- --struct device; -- --static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, -- size_t size) --{ -- return virt_to_phys(addr) | 0x80000000; --} -- --static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, -- struct page *page) --{ -- return page_to_phys(page) | 0x80000000; --} -- --static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) --{ -- return dma_addr & 0x7fffffff; --} -- --static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr) --{ --} -- --static inline int plat_dma_supported(struct device *dev, u64 mask) --{ -- /* -- * we fall back to GFP_DMA when the mask isn't all 1s, -- * so we can't guarantee allocations that must be -- * within a tighter range than GFP_DMA.. -- */ -- if (mask < DMA_BIT_MASK(24)) -- return 0; -- -- return 1; --} -- --static inline void plat_extra_sync_for_device(struct device *dev) --{ -- return; --} -- --static inline int plat_dma_mapping_error(struct device *dev, -- dma_addr_t dma_addr) --{ -- return 0; --} -- --static inline int plat_device_is_coherent(struct device *dev) --{ -- return 0; --} -- --#endif /* __ASM_MACH_LEMOTE_DMA_COHERENCE_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/mc146818rtc.h linux-2.6.30/arch/mips/include/asm/mach-lemote/mc146818rtc.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/mc146818rtc.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/mach-lemote/mc146818rtc.h 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-lemote/mc146818rtc.h linux-2.6.30.5/arch/mips/include/asm/mach-lemote/mc146818rtc.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-lemote/mc146818rtc.h 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-lemote/mc146818rtc.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,36 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public @@ -9493,9 +9216,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/mc146818rtc.h linu -#endif - -#endif /* __ASM_MACH_LEMOTE_MC146818RTC_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/pci.h linux-2.6.30/arch/mips/include/asm/mach-lemote/pci.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/pci.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/mach-lemote/pci.h 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-lemote/pci.h linux-2.6.30.5/arch/mips/include/asm/mach-lemote/pci.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-lemote/pci.h 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-lemote/pci.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2008 Zhang Le @@ -9527,9 +9250,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/pci.h linux-2.6.30 -#define LOONGSON2E_IO_PORT_BASE 0x1fd00000UL - -#endif /* !_LEMOTE_PCI_H_ */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/war.h linux-2.6.30/arch/mips/include/asm/mach-lemote/war.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/war.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/mach-lemote/war.h 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-lemote/war.h linux-2.6.30.5/arch/mips/include/asm/mach-lemote/war.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-lemote/war.h 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-lemote/war.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,25 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public @@ -9556,9 +9279,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-lemote/war.h linux-2.6.30 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_LEMOTE_WAR_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/clock.h linux-2.6.30/arch/mips/include/asm/mach-loongson/clock.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/clock.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/clock.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/clock.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/clock.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/clock.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/clock.h 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,64 @@ +#ifndef __ASM_MIPS_CLOCK_H +#define __ASM_MIPS_CLOCK_H @@ -9624,9 +9347,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/clock.h linux-2. +int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id); + +#endif /* __ASM_MIPS_CLOCK_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cmdline.h linux-2.6.30/arch/mips/include/asm/mach-loongson/cmdline.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cmdline.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/cmdline.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/cmdline.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/cmdline.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/cmdline.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/cmdline.h 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,9 @@ +/* machine-specific command line initialization */ +#ifdef CONFIG_SYS_HAS_MACH_PROM_INIT_CMDLINE @@ -9637,9 +9360,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cmdline.h linux- +} +#endif + -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h linux-2.6.30/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,59 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -9700,9 +9423,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cpu-feature-over +#define cpu_icache_snoops_remote_store 1 + +#endif /* __ASM_MACH_LEMOTE_CPU_FEATURE_OVERRIDES_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h linux-2.6.30/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,382 @@ +/* + * The header file of cs5536 sourth bridge. @@ -10086,10 +9809,10 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h +#define GPIOL_OUT_EN 0x04 + +#endif /* _CS5536_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h linux-2.6.30/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h 2009-06-14 20:25:19.000000000 +0200 -@@ -0,0 +1,26 @@ +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,27 @@ +/* + * cs5536 mfgpt header file + */ @@ -10099,6 +9822,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mf + +#include + ++extern u32 mfgpt_base; +extern void setup_mfgpt_timer(void); + +#if 1 @@ -10116,9 +9840,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mf +#define MFGPT0_SETUP (MFGPT_BASE + 6) + +#endif /*!_CS5536_MFGPT_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h linux-2.6.30/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,174 @@ +/* + * the definition file of cs5536 Virtual Support Module(VSM). @@ -10294,9 +10018,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pc +#define PCI_EHCI_FLADJ_REG 0x60 + +#endif /* _CS5536_PCI_H_ */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h linux-2.6.30/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,59 @@ +/* + * the Virtual Support Module(VSM) read/write interfaces @@ -10357,9 +10081,30 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vs + DEFINE_CS5536_MODULE(udc) +#endif +#endif /* _CS5536_VSM_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/dma-coherence.h linux-2.6.30/arch/mips/include/asm/mach-loongson/dma-coherence.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/dma-coherence.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/dma-coherence.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/dbg.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/dbg.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/dbg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/dbg.h 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,17 @@ ++/* ++ * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology ++ * ++ * 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. ++ */ ++ ++#ifndef _ASM_MACH_LOONGSON_DBG_H_ ++#define _ASM_MACH_LOONGSON_DBG_H_ ++ ++/* serial port print support */ ++extern void prom_putchar(char c); ++extern void prom_printf(char *fmt, ...); ++ ++#endif /* _ASM_MACH_LOONGSON_DBG_H_ */ +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/dma-coherence.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/dma-coherence.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/dma-coherence.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/dma-coherence.h 2009-08-22 11:43:28.000000000 +0200 @@ -0,0 +1,70 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -10390,7 +10135,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/dma-coherence.h + +static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) +{ -+#if defined(CONFIG_CPU_LOONGSON2F) & defined(CONFIG_64BIT) ++#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT) + return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff); +#else + return dma_addr & 0x7fffffff; @@ -10431,9 +10176,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/dma-coherence.h +} + +#endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/loongson.h linux-2.6.30/arch/mips/include/asm/mach-loongson/loongson.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/loongson.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/loongson.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/loongson.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/loongson.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/loongson.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/loongson.h 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2009 Philippe Vachon @@ -10754,9 +10499,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/loongson.h linux + +#endif /* __LOONGSON_H */ + -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/machine.h linux-2.6.30/arch/mips/include/asm/mach-loongson/machine.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/machine.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/machine.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/machine.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/machine.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/machine.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/machine.h 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,76 @@ +/* + * board-specific header file @@ -10834,9 +10579,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/machine.h linux- +#endif + +#endif /* ! __MACHINE_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/mc146818rtc.h linux-2.6.30/arch/mips/include/asm/mach-loongson/mc146818rtc.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/mc146818rtc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/mc146818rtc.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/mc146818rtc.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/mc146818rtc.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/mc146818rtc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/mc146818rtc.h 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,36 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -10874,9 +10619,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/mc146818rtc.h li +#endif + +#endif /* __ASM_MACH_LOONGSON_MC146818RTC_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/mem.h linux-2.6.30/arch/mips/include/asm/mach-loongson/mem.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/mem.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/mem.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/mem.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/mem.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/mem.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/mem.h 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,31 @@ +#ifndef __MEM_H +#define __MEM_H @@ -10909,9 +10654,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/mem.h linux-2.6. +#endif + +#endif /* !__MEM_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/pci.h linux-2.6.30/arch/mips/include/asm/mach-loongson/pci.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/pci.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/pci.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/pci.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/pci.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/pci.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/pci.h 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2008 Zhang Le @@ -10972,9 +10717,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/pci.h linux-2.6. + + +#endif /* !_LOONGSON_PCI_H_ */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/war.h linux-2.6.30/arch/mips/include/asm/mach-loongson/war.h ---- linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/war.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/include/asm/mach-loongson/war.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/war.h linux-2.6.30.5/arch/mips/include/asm/mach-loongson/war.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mach-loongson/war.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/include/asm/mach-loongson/war.h 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -11001,9 +10746,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mach-loongson/war.h linux-2.6. +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_LOONGSON_WAR_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mips-boards/bonito64.h linux-2.6.30/arch/mips/include/asm/mips-boards/bonito64.h ---- linux-2.6.30.orig/arch/mips/include/asm/mips-boards/bonito64.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/mips-boards/bonito64.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/mips-boards/bonito64.h linux-2.6.30.5/arch/mips/include/asm/mips-boards/bonito64.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/mips-boards/bonito64.h 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/include/asm/mips-boards/bonito64.h 2009-08-21 21:18:06.000000000 +0200 @@ -26,11 +26,6 @@ /* offsets from base register */ #define BONITO(x) (x) @@ -11016,9 +10761,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/mips-boards/bonito64.h linux-2 #else /* -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/page.h linux-2.6.30/arch/mips/include/asm/page.h ---- linux-2.6.30.orig/arch/mips/include/asm/page.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/page.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/page.h linux-2.6.30.5/arch/mips/include/asm/page.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/page.h 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/include/asm/page.h 2009-08-21 21:18:06.000000000 +0200 @@ -179,8 +179,9 @@ #endif @@ -11031,9 +10776,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/page.h linux-2.6.30/arch/mips/ #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/pci.h linux-2.6.30/arch/mips/include/asm/pci.h ---- linux-2.6.30.orig/arch/mips/include/asm/pci.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/pci.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/pci.h linux-2.6.30.5/arch/mips/include/asm/pci.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/pci.h 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/include/asm/pci.h 2009-08-21 21:18:06.000000000 +0200 @@ -56,7 +56,7 @@ /* * board supplied pci irq fixup routine @@ -11043,9 +10788,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/pci.h linux-2.6.30/arch/mips/i /* Can be used to override the logic in pci_scan_bus for skipping -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/pgtable.h linux-2.6.30/arch/mips/include/asm/pgtable.h ---- linux-2.6.30.orig/arch/mips/include/asm/pgtable.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/pgtable.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/pgtable.h linux-2.6.30.5/arch/mips/include/asm/pgtable.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/pgtable.h 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/include/asm/pgtable.h 2009-08-21 21:18:06.000000000 +0200 @@ -370,6 +370,19 @@ #include @@ -11066,9 +10811,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/pgtable.h linux-2.6.30/arch/mi * We provide our own get_unmapped area to cope with the virtual aliasing * constraints placed on us by the cache architecture. */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/stackframe.h linux-2.6.30/arch/mips/include/asm/stackframe.h ---- linux-2.6.30.orig/arch/mips/include/asm/stackframe.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/stackframe.h 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/include/asm/stackframe.h linux-2.6.30.5/arch/mips/include/asm/stackframe.h +--- linux-2.6.30.5.orig/arch/mips/include/asm/stackframe.h 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/include/asm/stackframe.h 2009-08-21 21:18:06.000000000 +0200 @@ -117,6 +117,20 @@ .endm #else @@ -11090,94 +10835,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/include/asm/stackframe.h linux-2.6.30/arch #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32) lui k1, %hi(kernelsp) #else -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/suspend.h linux-2.6.30/arch/mips/include/asm/suspend.h ---- linux-2.6.30.orig/arch/mips/include/asm/suspend.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/suspend.h 2009-06-14 20:25:19.000000000 +0200 -@@ -1,6 +1,9 @@ - #ifndef __ASM_SUSPEND_H - #define __ASM_SUSPEND_H - --/* Somewhen... Maybe :-) */ -+static inline int arch_prepare_suspend(void) { return 0; } -+ -+/* References to section boundaries */ -+extern const void __nosave_begin, __nosave_end; - - #endif /* __ASM_SUSPEND_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/txx9/generic.h linux-2.6.30/arch/mips/include/asm/txx9/generic.h ---- linux-2.6.30.orig/arch/mips/include/asm/txx9/generic.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/txx9/generic.h 2009-06-14 20:25:19.000000000 +0200 -@@ -37,7 +37,7 @@ - void (*arch_init)(void); - void (*device_init)(void); - #ifdef CONFIG_PCI -- int (*pci_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin); -+ int (*pci_map_irq)(struct pci_dev *dev, u8 slot, u8 pin); - #endif - }; - extern struct txx9_board_vec *txx9_board_vec; -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/txx9/jmr3927.h linux-2.6.30/arch/mips/include/asm/txx9/jmr3927.h ---- linux-2.6.30.orig/arch/mips/include/asm/txx9/jmr3927.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/txx9/jmr3927.h 2009-06-14 20:25:19.000000000 +0200 -@@ -175,6 +175,6 @@ - void jmr3927_prom_init(void); - void jmr3927_irq_setup(void); - struct pci_dev; --int jmr3927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); -+int jmr3927_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin); - - #endif /* __ASM_TXX9_JMR3927_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/txx9/rbtx4927.h linux-2.6.30/arch/mips/include/asm/txx9/rbtx4927.h ---- linux-2.6.30.orig/arch/mips/include/asm/txx9/rbtx4927.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/txx9/rbtx4927.h 2009-06-14 20:25:19.000000000 +0200 -@@ -87,6 +87,6 @@ - void rbtx4927_prom_init(void); - void rbtx4927_irq_setup(void); - struct pci_dev; --int rbtx4927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); -+int rbtx4927_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin); - - #endif /* __ASM_TXX9_RBTX4927_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/txx9/rbtx4938.h linux-2.6.30/arch/mips/include/asm/txx9/rbtx4938.h ---- linux-2.6.30.orig/arch/mips/include/asm/txx9/rbtx4938.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/txx9/rbtx4938.h 2009-06-14 20:25:19.000000000 +0200 -@@ -140,6 +140,6 @@ - void rbtx4938_prom_init(void); - void rbtx4938_irq_setup(void); - struct pci_dev; --int rbtx4938_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); -+int rbtx4938_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin); - - #endif /* __ASM_TXX9_RBTX4938_H */ -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/txx9/tx4938.h linux-2.6.30/arch/mips/include/asm/txx9/tx4938.h ---- linux-2.6.30.orig/arch/mips/include/asm/txx9/tx4938.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/txx9/tx4938.h 2009-06-14 20:25:19.000000000 +0200 -@@ -287,7 +287,7 @@ - void tx4938_report_pci1clk(void); - int tx4938_pciclk66_setup(void); - struct pci_dev; --int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot); -+int tx4938_pcic1_map_irq(struct pci_dev *dev, u8 slot); - void tx4938_setup_pcierr_irq(void); - void tx4938_irq_init(void); - void tx4938_mtd_init(int ch); -diff -Nur linux-2.6.30.orig/arch/mips/include/asm/txx9/tx4939.h linux-2.6.30/arch/mips/include/asm/txx9/tx4939.h ---- linux-2.6.30.orig/arch/mips/include/asm/txx9/tx4939.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/include/asm/txx9/tx4939.h 2009-06-14 20:25:19.000000000 +0200 -@@ -534,8 +534,8 @@ - int tx4939_report_pciclk(void); - void tx4939_report_pci1clk(void); - struct pci_dev; --int tx4939_pcic1_map_irq(const struct pci_dev *dev, u8 slot); --int tx4939_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); -+int tx4939_pcic1_map_irq(struct pci_dev *dev, u8 slot); -+int tx4939_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin); - void tx4939_setup_pcierr_irq(void); - void tx4939_irq_init(void); - int tx4939_irq(void); -diff -Nur linux-2.6.30.orig/arch/mips/Kconfig linux-2.6.30/arch/mips/Kconfig ---- linux-2.6.30.orig/arch/mips/Kconfig 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/Kconfig 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/Kconfig linux-2.6.30.5/arch/mips/Kconfig +--- linux-2.6.30.5.orig/arch/mips/Kconfig 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/Kconfig 2009-08-21 21:17:59.000000000 +0200 @@ -6,7 +6,7 @@ select HAVE_ARCH_KGDB # Horrible source of confusion. Die, die, die ... @@ -11187,7 +10847,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/Kconfig linux-2.6.30/arch/mips/Kconfig mainmenu "Linux/MIPS Kernel Configuration" -@@ -154,30 +154,15 @@ +@@ -154,30 +154,19 @@ select SYS_SUPPORTS_64BIT_KERNEL if BROKEN select SYS_SUPPORTS_LITTLE_ENDIAN @@ -11212,11 +10872,16 @@ diff -Nur linux-2.6.30.orig/arch/mips/Kconfig linux-2.6.30/arch/mips/Kconfig - select SYS_HAS_EARLY_PRINTK - select GENERIC_ISA_DMA_SUPPORT_BROKEN - select CPU_HAS_WB -+config MACH_LOONGSON -+ bool "Loongson family of machines" - help +- help - Lemote Fulong mini-PC board based on the Chinese Loongson-2E CPU and - an FPGA northbridge ++config MACH_LOONGSON ++ bool "Loongson family of machines" ++ select HAVE_KERNEL_GZIP ++ select HAVE_KERNEL_BZIP2 ++ select HAVE_KERNEL_LZMA ++ select LOONGSON_PLATFORM_DEVICES ++ help + This enables the support of Loongson family of machines. + + Loongson is a family of general-purpose MIPS-compatible CPUs. @@ -11226,7 +10891,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/Kconfig linux-2.6.30/arch/mips/Kconfig config MIPS_MALTA bool "MIPS Malta board" -@@ -643,6 +628,7 @@ +@@ -643,6 +632,7 @@ source "arch/mips/txx9/Kconfig" source "arch/mips/vr41xx/Kconfig" source "arch/mips/cavium-octeon/Kconfig" @@ -11234,7 +10899,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/Kconfig linux-2.6.30/arch/mips/Kconfig endmenu -@@ -1005,16 +991,29 @@ +@@ -1005,16 +995,29 @@ prompt "CPU type" default CPU_R4X00 @@ -11270,7 +10935,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/Kconfig linux-2.6.30/arch/mips/Kconfig config CPU_MIPS32_R1 bool "MIPS32 Release 1" depends on SYS_HAS_CPU_MIPS32_R1 -@@ -1253,7 +1252,16 @@ +@@ -1253,7 +1256,16 @@ endchoice @@ -11288,17 +10953,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/Kconfig linux-2.6.30/arch/mips/Kconfig bool config SYS_HAS_CPU_MIPS32_R1 -@@ -2121,6 +2129,9 @@ - - menu "Power management options" - -+config ARCH_HIBERNATION_POSSIBLE -+ def_bool y -+ - config ARCH_SUSPEND_POSSIBLE - def_bool y - depends on !SMP -@@ -2129,6 +2140,23 @@ +@@ -2129,6 +2141,23 @@ endmenu @@ -11322,36 +10977,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/Kconfig linux-2.6.30/arch/mips/Kconfig source "net/Kconfig" source "drivers/Kconfig" -diff -Nur linux-2.6.30.orig/arch/mips/kernel/asm-offsets.c linux-2.6.30/arch/mips/kernel/asm-offsets.c ---- linux-2.6.30.orig/arch/mips/kernel/asm-offsets.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/kernel/asm-offsets.c 2009-06-14 20:25:19.000000000 +0200 -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -326,3 +327,15 @@ - BLANK(); - } - #endif -+ -+#ifdef CONFIG_HIBERNATION -+void output_pbe_defines(void) -+{ -+ COMMENT(" Linux struct pbe offsets. "); -+ OFFSET(PBE_ADDRESS, pbe, address); -+ OFFSET(PBE_ORIG_ADDRESS, pbe, orig_address); -+ OFFSET(PBE_NEXT, pbe, next); -+ DEFINE(PBE_SIZE, sizeof(struct pbe)); -+ BLANK(); -+} -+#endif -diff -Nur linux-2.6.30.orig/arch/mips/kernel/i8259.c linux-2.6.30/arch/mips/kernel/i8259.c ---- linux-2.6.30.orig/arch/mips/kernel/i8259.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/kernel/i8259.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/kernel/i8259.c linux-2.6.30.5/arch/mips/kernel/i8259.c +--- linux-2.6.30.5.orig/arch/mips/kernel/i8259.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/kernel/i8259.c 2009-08-21 21:18:06.000000000 +0200 @@ -177,10 +177,12 @@ outb(cached_slave_mask, PIC_SLAVE_IMR); outb(0x60+(irq&7), PIC_SLAVE_CMD);/* 'Specific EOI' to slave */ @@ -11365,9 +10993,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/kernel/i8259.c linux-2.6.30/arch/mips/kern } smtc_im_ack_irq(irq); spin_unlock_irqrestore(&i8259A_lock, flags); -diff -Nur linux-2.6.30.orig/arch/mips/kernel/loongson2f_freq.c linux-2.6.30/arch/mips/kernel/loongson2f_freq.c ---- linux-2.6.30.orig/arch/mips/kernel/loongson2f_freq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/kernel/loongson2f_freq.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/kernel/loongson2f_freq.c linux-2.6.30.5/arch/mips/kernel/loongson2f_freq.c +--- linux-2.6.30.5.orig/arch/mips/kernel/loongson2f_freq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/kernel/loongson2f_freq.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,216 @@ +/* + * arch/mips/kernel/cpufreq.c @@ -11585,9 +11213,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/kernel/loongson2f_freq.c linux-2.6.30/arch +MODULE_AUTHOR("Yanhua "); +MODULE_DESCRIPTION("cpufreq driver for Loongson2F"); +MODULE_LICENSE("GPL"); -diff -Nur linux-2.6.30.orig/arch/mips/kernel/Makefile linux-2.6.30/arch/mips/kernel/Makefile ---- linux-2.6.30.orig/arch/mips/kernel/Makefile 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/kernel/Makefile 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/kernel/Makefile linux-2.6.30.5/arch/mips/kernel/Makefile +--- linux-2.6.30.5.orig/arch/mips/kernel/Makefile 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/kernel/Makefile 2009-08-21 21:18:06.000000000 +0200 @@ -73,6 +73,7 @@ obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o @@ -11596,20 +11224,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/kernel/Makefile linux-2.6.30/arch/mips/ker obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_PROC_FS) += proc.o -diff -Nur linux-2.6.30.orig/arch/mips/kernel/smtc.c linux-2.6.30/arch/mips/kernel/smtc.c ---- linux-2.6.30.orig/arch/mips/kernel/smtc.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/kernel/smtc.c 2009-06-14 20:25:19.000000000 +0200 -@@ -924,6 +924,7 @@ - int irq = MIPS_CPU_IRQ_BASE + 1; - - smtc_ipi_nq(&freeIPIq, pipi); -+ - switch (type_copy) { - case SMTC_CLOCK_TICK: - irq_enter(); -diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/bonito-irq.c linux-2.6.30/arch/mips/lemote/lm2e/bonito-irq.c ---- linux-2.6.30.orig/arch/mips/lemote/lm2e/bonito-irq.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/lemote/lm2e/bonito-irq.c 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/lemote/lm2e/bonito-irq.c linux-2.6.30.5/arch/mips/lemote/lm2e/bonito-irq.c +--- linux-2.6.30.5.orig/arch/mips/lemote/lm2e/bonito-irq.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/lemote/lm2e/bonito-irq.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,74 +0,0 @@ -/* - * Copyright 2001 MontaVista Software Inc. @@ -11685,9 +11302,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/bonito-irq.c linux-2.6.30/arch - - setup_irq(BONITO_IRQ_BASE + 10, &dma_timeout_irqaction); -} -diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/dbg_io.c linux-2.6.30/arch/mips/lemote/lm2e/dbg_io.c ---- linux-2.6.30.orig/arch/mips/lemote/lm2e/dbg_io.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/lemote/lm2e/dbg_io.c 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/lemote/lm2e/dbg_io.c linux-2.6.30.5/arch/mips/lemote/lm2e/dbg_io.c +--- linux-2.6.30.5.orig/arch/mips/lemote/lm2e/dbg_io.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/lemote/lm2e/dbg_io.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,146 +0,0 @@ -/* - * Copyright 2001 MontaVista Software Inc. @@ -11835,9 +11452,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/dbg_io.c linux-2.6.30/arch/mip - UART16550_WRITE(OFS_SEND_BUFFER, byte); - return 1; -} -diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/irq.c linux-2.6.30/arch/mips/lemote/lm2e/irq.c ---- linux-2.6.30.orig/arch/mips/lemote/lm2e/irq.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/lemote/lm2e/irq.c 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/lemote/lm2e/irq.c linux-2.6.30.5/arch/mips/lemote/lm2e/irq.c +--- linux-2.6.30.5.orig/arch/mips/lemote/lm2e/irq.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/lemote/lm2e/irq.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology @@ -11982,9 +11599,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/irq.c linux-2.6.30/arch/mips/l - setup_irq(MIPS_CPU_IRQ_BASE + 5, &cascade_irqaction); - -} -diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/Makefile linux-2.6.30/arch/mips/lemote/lm2e/Makefile ---- linux-2.6.30.orig/arch/mips/lemote/lm2e/Makefile 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/lemote/lm2e/Makefile 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/lemote/lm2e/Makefile linux-2.6.30.5/arch/mips/lemote/lm2e/Makefile +--- linux-2.6.30.5.orig/arch/mips/lemote/lm2e/Makefile 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/lemote/lm2e/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -# -# Makefile for Lemote Fulong mini-PC board. @@ -11993,9 +11610,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/Makefile linux-2.6.30/arch/mip -obj-y += setup.o prom.o reset.o irq.o pci.o bonito-irq.o dbg_io.o mem.o - -EXTRA_CFLAGS += -Werror -diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/mem.c linux-2.6.30/arch/mips/lemote/lm2e/mem.c ---- linux-2.6.30.orig/arch/mips/lemote/lm2e/mem.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/lemote/lm2e/mem.c 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/lemote/lm2e/mem.c linux-2.6.30.5/arch/mips/lemote/lm2e/mem.c +--- linux-2.6.30.5.orig/arch/mips/lemote/lm2e/mem.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/lemote/lm2e/mem.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,23 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it @@ -12020,9 +11637,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/mem.c linux-2.6.30/arch/mips/l - return addr >= __pa(high_memory) || - ((addr >= 0x10000000) && (addr < 0x20000000)); -} -diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/pci.c linux-2.6.30/arch/mips/lemote/lm2e/pci.c ---- linux-2.6.30.orig/arch/mips/lemote/lm2e/pci.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/lemote/lm2e/pci.c 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/lemote/lm2e/pci.c linux-2.6.30.5/arch/mips/lemote/lm2e/pci.c +--- linux-2.6.30.5.orig/arch/mips/lemote/lm2e/pci.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/lemote/lm2e/pci.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,97 +0,0 @@ -/* - * pci.c @@ -12121,9 +11738,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/pci.c linux-2.6.30/arch/mips/l -} - -arch_initcall(pcibios_init); -diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/prom.c linux-2.6.30/arch/mips/lemote/lm2e/prom.c ---- linux-2.6.30.orig/arch/mips/lemote/lm2e/prom.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/lemote/lm2e/prom.c 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/lemote/lm2e/prom.c linux-2.6.30.5/arch/mips/lemote/lm2e/prom.c +--- linux-2.6.30.5.orig/arch/mips/lemote/lm2e/prom.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/lemote/lm2e/prom.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,97 +0,0 @@ -/* - * Based on Ocelot Linux port, which is @@ -12222,9 +11839,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/prom.c linux-2.6.30/arch/mips/ -{ - putDebugChar(c); -} -diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/reset.c linux-2.6.30/arch/mips/lemote/lm2e/reset.c ---- linux-2.6.30.orig/arch/mips/lemote/lm2e/reset.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/lemote/lm2e/reset.c 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/lemote/lm2e/reset.c linux-2.6.30.5/arch/mips/lemote/lm2e/reset.c +--- linux-2.6.30.5.orig/arch/mips/lemote/lm2e/reset.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/lemote/lm2e/reset.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,41 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it @@ -12267,9 +11884,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/reset.c linux-2.6.30/arch/mips - _machine_halt = loongson2e_halt; - pm_power_off = loongson2e_power_off; -} -diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/setup.c linux-2.6.30/arch/mips/lemote/lm2e/setup.c ---- linux-2.6.30.orig/arch/mips/lemote/lm2e/setup.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/lemote/lm2e/setup.c 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/lemote/lm2e/setup.c linux-2.6.30.5/arch/mips/lemote/lm2e/setup.c +--- linux-2.6.30.5.orig/arch/mips/lemote/lm2e/setup.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/lemote/lm2e/setup.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,111 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION @@ -12382,9 +11999,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/lemote/lm2e/setup.c linux-2.6.30/arch/mips -#endif - -} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/bonito-irq.c linux-2.6.30/arch/mips/loongson/common/bonito-irq.c ---- linux-2.6.30.orig/arch/mips/loongson/common/bonito-irq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/bonito-irq.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/bonito-irq.c linux-2.6.30.5/arch/mips/loongson/common/bonito-irq.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/bonito-irq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/bonito-irq.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,78 @@ +/* + * Copyright 2001 MontaVista Software Inc. @@ -12464,9 +12081,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/bonito-irq.c linux-2.6.30/ + setup_irq(LOONGSON_DMATIMEOUT_IRQ, &dma_timeout_irqaction); +#endif +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/clock.c linux-2.6.30/arch/mips/loongson/common/clock.c ---- linux-2.6.30.orig/arch/mips/loongson/common/clock.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/clock.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/clock.c linux-2.6.30.5/arch/mips/loongson/common/clock.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/clock.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/clock.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,166 @@ +/* + * arch/mips/loongson/common/clock.c @@ -12634,9 +12251,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/clock.c linux-2.6.30/arch/ + spin_unlock_irqrestore(&loongson2f_wait_lock, flags); +} +EXPORT_SYMBOL_GPL(loongson2f_cpu_wait); -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cmdline.c linux-2.6.30/arch/mips/loongson/common/cmdline.c ---- linux-2.6.30.orig/arch/mips/loongson/common/cmdline.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/cmdline.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/cmdline.c linux-2.6.30.5/arch/mips/loongson/common/cmdline.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/cmdline.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/cmdline.c 2009-08-22 13:40:56.000000000 +0200 @@ -0,0 +1,57 @@ +/* + * Based on Ocelot Linux port, which is @@ -12691,13 +12308,13 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cmdline.c linux-2.6.30/arc + mach_prom_init_cmdline(); + + if ((strstr(arcs_cmdline, "console=")) == NULL) -+ strcat(arcs_cmdline, " console=ttyS0,115200"); ++ strcat(arcs_cmdline, " console=tty"); + if ((strstr(arcs_cmdline, "root=")) == NULL) -+ strcat(arcs_cmdline, " root=/dev/hda1"); ++ strcat(arcs_cmdline, " root=/dev/sda1"); +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_acc.c linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_acc.c ---- linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_acc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_acc.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_acc.c linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_acc.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_acc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_acc.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,156 @@ +/* + * the ACC Virtual Support Module of AMD CS5536 @@ -12855,9 +12472,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_acc.c linux- + + return conf_data; +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_ehci.c linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_ehci.c ---- linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_ehci.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_ehci.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_ehci.c linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_ehci.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_ehci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_ehci.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,166 @@ +/* + * the EHCI Virtual Support Module of AMD CS5536 @@ -13025,9 +12642,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_ehci.c linux + + return conf_data; +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_flash.c linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_flash.c ---- linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_flash.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_flash.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_flash.c linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_flash.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_flash.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_flash.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,452 @@ +/* + * the FLASH Virtual Support Module of AMD CS5536 @@ -13481,9 +13098,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_flash.c linu + return conf_data; +} +#endif /* CONFIG_CS5536_NOR_FLASH */ -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_ide.c linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_ide.c ---- linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_ide.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_ide.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_ide.c linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_ide.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_ide.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_ide.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,194 @@ +/* + * the IDE Virtual Support Module of AMD CS5536 @@ -13679,9 +13296,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_ide.c linux- + + return conf_data; +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_isa.c linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_isa.c ---- linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_isa.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_isa.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_isa.c linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_isa.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_isa.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_isa.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,376 @@ +/* + * the ISA Virtual Support Module of AMD CS5536 @@ -14059,10 +13676,10 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_isa.c linux- + + return conf_data; +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c ---- linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c 2009-06-14 20:25:19.000000000 +0200 -@@ -0,0 +1,257 @@ +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,241 @@ +/* + * CS5536 General timer functions + * @@ -14095,7 +13712,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c linu +DEFINE_SPINLOCK(mfgpt_lock); +EXPORT_SYMBOL(mfgpt_lock); + -+static u32 mfgpt_base; ++u32 mfgpt_base; + +/* + * Initialize the MFGPT timer. @@ -14170,7 +13787,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c linu + +static struct clock_event_device mfgpt_clockevent = { + .name = "mfgpt", -+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_MODE_ONESHOT, ++ .features = CLOCK_EVT_FEAT_PERIODIC, + .set_mode = init_mfgpt_timer, + .set_next_event = mfgpt_next_event, + .irq = CS5536_MFGPT_INTR, @@ -14198,7 +13815,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c linu + +static struct irqaction irq5 = { + .handler = timer_interrupt, -+ .flags = IRQF_DISABLED | IRQF_NOBALANCING, ++ .flags = IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING, + .name = "timer" +}; + @@ -14261,24 +13878,8 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c linu + * count), it cannot be newer. + */ + jifs = jiffies; -+ /* latch the counter */ -+ outw(inw(MFGPT0_SETUP) | 0x0200, MFGPT0_SETUP); -+ /* read the latched count */ ++ /* read the count */ + count = inw(MFGPT0_CNT); -+ /* restart the counter */ -+ outw(inw(MFGPT0_SETUP) & 0xfdff, MFGPT0_SETUP); -+ -+ /* reset the latch if count > max + 1 */ -+ if (count > COMPARE) { -+ /* set comparator2 */ -+ outw(COMPARE, MFGPT0_CMP2); -+ /* set counter to 0 */ -+ outw(0, MFGPT0_CNT); -+ /* enable counter, comparator2 to event mode, 14.318MHz clock */ -+ outw(0xe310, MFGPT0_SETUP); -+ -+ count = COMPARE - 1; -+ } + + /* + * It's possible for count to appear to go the wrong way for this @@ -14290,7 +13891,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c linu + * Previous attempts to handle these cases intelligently were buggy, so + * we just do the simple thing now. + */ -+ if (count > old_count && jifs == old_jifs) ++ if (count < old_count && jifs == old_jifs) + count = old_count; + + old_count = count; @@ -14320,9 +13921,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c linu +} + +arch_initcall(init_mfgpt_clocksource); -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_ohci.c linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_ohci.c ---- linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_ohci.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_ohci.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_ohci.c linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_ohci.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_ohci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_ohci.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,168 @@ +/* + * the OHCI Virtual Support Module of AMD CS5536 @@ -14492,9 +14093,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_ohci.c linux + + return conf_data; +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_otg.c linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_otg.c ---- linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_otg.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_otg.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_otg.c linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_otg.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_otg.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_otg.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,138 @@ +/* + * the OTG Virtual Support Module of AMD CS5536 @@ -14634,9 +14235,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_otg.c linux- + + return conf_data; +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_pci.c linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_pci.c ---- linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_pci.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_pci.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_pci.c linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_pci.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_pci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_pci.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,126 @@ +/* + * read/write operation to the PCI config space of CS5536 @@ -14764,9 +14365,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_pci.c linux- + } + return data; +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_udc.c linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_udc.c ---- linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_udc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/cs5536/cs5536_udc.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_udc.c linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_udc.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/cs5536_udc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/cs5536/cs5536_udc.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,143 @@ +/* + * the UDC Virtual Support Module of AMD CS5536 @@ -14911,9 +14512,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/cs5536_udc.c linux- + + return conf_data; +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/Makefile linux-2.6.30/arch/mips/loongson/common/cs5536/Makefile ---- linux-2.6.30.orig/arch/mips/loongson/common/cs5536/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/cs5536/Makefile 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/Makefile linux-2.6.30.5/arch/mips/loongson/common/cs5536/Makefile +--- linux-2.6.30.5.orig/arch/mips/loongson/common/cs5536/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/cs5536/Makefile 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,25 @@ +# +# Makefile for CS5536 support. @@ -14940,9 +14541,47 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/cs5536/Makefile linux-2.6. +obj-$(CONFIG_CS5536_MFGPT) += cs5536_mfgpt.o + +EXTRA_CFLAGS += -Werror -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/early_printk.c linux-2.6.30/arch/mips/loongson/common/early_printk.c ---- linux-2.6.30.orig/arch/mips/loongson/common/early_printk.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/early_printk.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/dbg.c linux-2.6.30.5/arch/mips/loongson/common/dbg.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/dbg.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/dbg.c 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology ++ * ++ * 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 ++#include ++ ++#define PROM_PRINTF_BUF_LEN 1024 ++ ++void prom_printf(char *fmt, ...) ++{ ++ static char buf[PROM_PRINTF_BUF_LEN]; ++ va_list args; ++ char *ptr; ++ ++ ++ va_start(args, fmt); ++ vscnprintf(buf, sizeof(buf), fmt, args); ++ ++ ptr = buf; ++ ++ while (*ptr != 0) { ++ if (*ptr == '\n') ++ prom_putchar('\r'); ++ ++ prom_putchar(*ptr++); ++ } ++ va_end(args); ++} +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/early_printk.c linux-2.6.30.5/arch/mips/loongson/common/early_printk.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/early_printk.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/early_printk.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,28 @@ +/* early printk support + * @@ -14972,9 +14611,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/early_printk.c linux-2.6.3 + + writeb(c, (u8 *) (uart_base + UART_TX)); +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/env.c linux-2.6.30/arch/mips/loongson/common/env.c ---- linux-2.6.30.orig/arch/mips/loongson/common/env.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/env.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/env.c linux-2.6.30.5/arch/mips/loongson/common/env.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/env.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/env.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,59 @@ +/* + * Based on Ocelot Linux port, which is @@ -15035,10 +14674,10 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/env.c linux-2.6.30/arch/mi + pr_info("busclock=%ld, cpuclock=%ld, memsize=%ld, highmemsize=%ld\n", + bus_clock, cpu_clock_freq, memsize, highmemsize); +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/init.c linux-2.6.30/arch/mips/loongson/common/init.c ---- linux-2.6.30.orig/arch/mips/loongson/common/init.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/init.c 2009-06-14 20:25:19.000000000 +0200 -@@ -0,0 +1,54 @@ +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/init.c linux-2.6.30.5/arch/mips/loongson/common/init.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/init.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/init.c 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,65 @@ +/* + * Based on Ocelot Linux port, which is + * Copyright 2001 MontaVista Software Inc. @@ -15059,6 +14698,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/init.c linux-2.6.30/arch/m +#include + +#include ++#include + +#include + @@ -15073,6 +14713,14 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/init.c linux-2.6.30/arch/m +} +#endif + ++/* stop all perf counters by default ++ * $24 is the control register of loongson perf counter ++ */ ++static inline void stop_perf_counters(void) ++{ ++ __write_64bit_c0_register($24, 0, 0); ++} ++ +void __init prom_init(void) +{ + /* init several base address */ @@ -15084,6 +14732,8 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/init.c linux-2.6.30/arch/m + ioremap(LOONGSON_ADDRWINCFG_BASE, + LOONGSON_ADDRWINCFG_SIZE)); +#endif ++ /* stop all perf counters */ ++ stop_perf_counters(); + + prom_init_cmdline(); + prom_init_env(); @@ -15093,10 +14743,10 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/init.c linux-2.6.30/arch/m +void __init prom_free_prom_memory(void) +{ +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/irq.c linux-2.6.30/arch/mips/loongson/common/irq.c ---- linux-2.6.30.orig/arch/mips/loongson/common/irq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/irq.c 2009-06-14 20:25:19.000000000 +0200 -@@ -0,0 +1,132 @@ +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/irq.c linux-2.6.30.5/arch/mips/loongson/common/irq.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/irq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/irq.c 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,120 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net @@ -15169,15 +14819,6 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/irq.c linux-2.6.30/arch/mi + .name = "cascade", +}; + -+/* -+ * fuloong2f and yeeloong2f share the cpu perf counter interrupt and the north -+ * bridge interrupt in IP6, so, the ip6_irqaction should be sharable. -+ * otherwise, we will can not request the perf counter irq(setup the perf -+ * counter irq handler) in op_model_loongson2.c. -+ */ -+ -+#if defined(CONFIG_OPROFILE) && \ -+ (defined(CONFIG_LEMOTE_FULOONG2F) || defined(CONFIG_LEMOTE_YEELOONG2F)) +irqreturn_t ip6_action(int cpl, void *dev_id) +{ + return IRQ_HANDLED; @@ -15188,9 +14829,6 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/irq.c linux-2.6.30/arch/mi + .name = "cascade", + .flags = IRQF_SHARED, +}; -+#else -+#define ip6_irqaction cascade_irqaction -+#endif + +void __init arch_init_irq(void) +{ @@ -15229,9 +14867,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/irq.c linux-2.6.30/arch/mi + /* setup source bridge irq (i8259) */ + setup_irq(LOONGSON_SOUTH_BRIDGE_IRQ, &cascade_irqaction); +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/machtype.c linux-2.6.30/arch/mips/loongson/common/machtype.c ---- linux-2.6.30.orig/arch/mips/loongson/common/machtype.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/machtype.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/machtype.c linux-2.6.30.5/arch/mips/loongson/common/machtype.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/machtype.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/machtype.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology @@ -15283,9 +14921,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/machtype.c linux-2.6.30/ar + return 0; +} +__setup("machtype=", machtype_setup); -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/Makefile linux-2.6.30/arch/mips/loongson/common/Makefile ---- linux-2.6.30.orig/arch/mips/loongson/common/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/Makefile 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/Makefile linux-2.6.30.5/arch/mips/loongson/common/Makefile +--- linux-2.6.30.5.orig/arch/mips/loongson/common/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/Makefile 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,37 @@ +# +# Makefile for loongson based machines. @@ -15297,7 +14935,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/Makefile linux-2.6.30/arch +# +# Early printk support +# -+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o ++obj-$(CONFIG_EARLY_PRINTK) += early_printk.o dbg.o + +# +# Enable RTC Class support @@ -15324,9 +14962,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/Makefile linux-2.6.30/arch +obj-$(CONFIG_SERIAL_8250) += serial.o + +EXTRA_CFLAGS += -Werror -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/mem.c linux-2.6.30/arch/mips/loongson/common/mem.c ---- linux-2.6.30.orig/arch/mips/loongson/common/mem.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/mem.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/mem.c linux-2.6.30.5/arch/mips/loongson/common/mem.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/mem.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/mem.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,116 @@ +/* + * This program is free software; you can redistribute it and/or modify it @@ -15444,9 +15082,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/mem.c linux-2.6.30/arch/mi + +late_initcall(find_vga_mem_init); +#endif /* !CONFIG_CPU_LOONGSON2F */ -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/pci.c linux-2.6.30/arch/mips/loongson/common/pci.c ---- linux-2.6.30.orig/arch/mips/loongson/common/pci.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/pci.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/pci.c linux-2.6.30.5/arch/mips/loongson/common/pci.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/pci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/pci.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology @@ -15557,9 +15195,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/pci.c linux-2.6.30/arch/mi +} + +arch_initcall(pcibios_init); -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/reset.c linux-2.6.30/arch/mips/loongson/common/reset.c ---- linux-2.6.30.orig/arch/mips/loongson/common/reset.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/reset.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/reset.c linux-2.6.30.5/arch/mips/loongson/common/reset.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/reset.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/reset.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,38 @@ +/* + * This program is free software; you can redistribute it and/or modify it @@ -15599,9 +15237,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/reset.c linux-2.6.30/arch/ + _machine_halt = loongson_halt; + pm_power_off = loongson_halt; +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/rtc.c linux-2.6.30/arch/mips/loongson/common/rtc.c ---- linux-2.6.30.orig/arch/mips/loongson/common/rtc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/rtc.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/rtc.c linux-2.6.30.5/arch/mips/loongson/common/rtc.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/rtc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/rtc.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,54 @@ +/* + * Registration of Cobalt RTC platform device. @@ -15657,9 +15295,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/rtc.c linux-2.6.30/arch/mi +} + +device_initcall(rtc_cmos_init); -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/serial.c linux-2.6.30/arch/mips/loongson/common/serial.c ---- linux-2.6.30.orig/arch/mips/loongson/common/serial.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/serial.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/serial.c linux-2.6.30.5/arch/mips/loongson/common/serial.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/serial.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/serial.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,66 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -15727,9 +15365,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/serial.c linux-2.6.30/arch +} + +device_initcall(serial_init); -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/setup.c linux-2.6.30/arch/mips/loongson/common/setup.c ---- linux-2.6.30.orig/arch/mips/loongson/common/setup.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/setup.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/setup.c linux-2.6.30.5/arch/mips/loongson/common/setup.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/setup.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/setup.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,74 @@ +/* + * board dependent setup routines @@ -15805,9 +15443,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/setup.c linux-2.6.30/arch/ + + loongson_screeninfo_setup(); +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/time.c linux-2.6.30/arch/mips/loongson/common/time.c ---- linux-2.6.30.orig/arch/mips/loongson/common/time.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/common/time.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/common/time.c linux-2.6.30.5/arch/mips/loongson/common/time.c +--- linux-2.6.30.5.orig/arch/mips/loongson/common/time.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/common/time.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,34 @@ +/* + * board dependent boot routines @@ -15843,9 +15481,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/common/time.c linux-2.6.30/arch/m + setup_mfgpt_timer(); +#endif +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/fuloong-2e/irq.c linux-2.6.30/arch/mips/loongson/fuloong-2e/irq.c ---- linux-2.6.30.orig/arch/mips/loongson/fuloong-2e/irq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/fuloong-2e/irq.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/fuloong-2e/irq.c linux-2.6.30.5/arch/mips/loongson/fuloong-2e/irq.c +--- linux-2.6.30.5.orig/arch/mips/loongson/fuloong-2e/irq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/fuloong-2e/irq.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology @@ -15905,9 +15543,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/fuloong-2e/irq.c linux-2.6.30/arc + LOONGSON_INTEDGE = LOONGSON_ICU_SYSTEMERR | LOONGSON_ICU_MASTERERR | + LOONGSON_ICU_RETRYERR | LOONGSON_ICU_MBOXES; +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/fuloong-2e/Makefile linux-2.6.30/arch/mips/loongson/fuloong-2e/Makefile ---- linux-2.6.30.orig/arch/mips/loongson/fuloong-2e/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/fuloong-2e/Makefile 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/fuloong-2e/Makefile linux-2.6.30.5/arch/mips/loongson/fuloong-2e/Makefile +--- linux-2.6.30.5.orig/arch/mips/loongson/fuloong-2e/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/fuloong-2e/Makefile 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,7 @@ +# +# Makefile for fuloong-2e @@ -15916,9 +15554,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/fuloong-2e/Makefile linux-2.6.30/ +obj-y += irq.o reset.o + +EXTRA_CFLAGS += -Werror -diff -Nur linux-2.6.30.orig/arch/mips/loongson/fuloong-2e/reset.c linux-2.6.30/arch/mips/loongson/fuloong-2e/reset.c ---- linux-2.6.30.orig/arch/mips/loongson/fuloong-2e/reset.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/fuloong-2e/reset.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/fuloong-2e/reset.c linux-2.6.30.5/arch/mips/loongson/fuloong-2e/reset.c +--- linux-2.6.30.5.orig/arch/mips/loongson/fuloong-2e/reset.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/fuloong-2e/reset.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,26 @@ +/* Board-specific reboot/shutdown routines + * Copyright (c) 2009 Philippe Vachon @@ -15946,9 +15584,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/fuloong-2e/reset.c linux-2.6.30/a +void mach_prepare_shutdown(void) +{ +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/fuloong-2f/irq.c linux-2.6.30/arch/mips/loongson/fuloong-2f/irq.c ---- linux-2.6.30.orig/arch/mips/loongson/fuloong-2f/irq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/fuloong-2f/irq.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/fuloong-2f/irq.c linux-2.6.30.5/arch/mips/loongson/fuloong-2f/irq.c +--- linux-2.6.30.5.orig/arch/mips/loongson/fuloong-2f/irq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/fuloong-2f/irq.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology @@ -16003,18 +15641,18 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/fuloong-2f/irq.c linux-2.6.30/arc + LOONGSON_INTPOL = LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1; + LOONGSON_INTEDGE &= ~(LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1); +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/fuloong-2f/Makefile linux-2.6.30/arch/mips/loongson/fuloong-2f/Makefile ---- linux-2.6.30.orig/arch/mips/loongson/fuloong-2f/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/fuloong-2f/Makefile 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/fuloong-2f/Makefile linux-2.6.30.5/arch/mips/loongson/fuloong-2f/Makefile +--- linux-2.6.30.5.orig/arch/mips/loongson/fuloong-2f/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/fuloong-2f/Makefile 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,5 @@ +# +# Makefile for fuloong-2f +# + +obj-y += irq.o reset.o -diff -Nur linux-2.6.30.orig/arch/mips/loongson/fuloong-2f/reset.c linux-2.6.30/arch/mips/loongson/fuloong-2f/reset.c ---- linux-2.6.30.orig/arch/mips/loongson/fuloong-2f/reset.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/fuloong-2f/reset.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/fuloong-2f/reset.c linux-2.6.30.5/arch/mips/loongson/fuloong-2f/reset.c +--- linux-2.6.30.5.orig/arch/mips/loongson/fuloong-2f/reset.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/fuloong-2f/reset.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,65 @@ +/* Board-specific reboot/shutdown routines + * @@ -16081,10 +15719,620 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/fuloong-2f/reset.c linux-2.6.30/a + writel(val, (u32 *) (gpio_base + GPIOL_OUT_VAL)); + mmiowb(); +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/Kconfig linux-2.6.30/arch/mips/loongson/Kconfig ---- linux-2.6.30.orig/arch/mips/loongson/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/Kconfig 2009-06-14 20:25:19.000000000 +0200 -@@ -0,0 +1,135 @@ +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/image/cache.c linux-2.6.30.5/arch/mips/loongson/image/cache.c +--- linux-2.6.30.5.orig/arch/mips/loongson/image/cache.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/image/cache.c 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,42 @@ ++#include ++ ++#define cache32_unroll32(base, op) \ ++ __asm__ __volatile__( \ ++ " .set push \n" \ ++ " .set noreorder \n" \ ++ " .set mips3 \n" \ ++ " cache %1, 0x000(%0); cache %1, 0x020(%0) \n" \ ++ " cache %1, 0x040(%0); cache %1, 0x060(%0) \n" \ ++ " cache %1, 0x080(%0); cache %1, 0x0a0(%0) \n" \ ++ " cache %1, 0x0c0(%0); cache %1, 0x0e0(%0) \n" \ ++ " cache %1, 0x100(%0); cache %1, 0x120(%0) \n" \ ++ " cache %1, 0x140(%0); cache %1, 0x160(%0) \n" \ ++ " cache %1, 0x180(%0); cache %1, 0x1a0(%0) \n" \ ++ " cache %1, 0x1c0(%0); cache %1, 0x1e0(%0) \n" \ ++ " cache %1, 0x200(%0); cache %1, 0x220(%0) \n" \ ++ " cache %1, 0x240(%0); cache %1, 0x260(%0) \n" \ ++ " cache %1, 0x280(%0); cache %1, 0x2a0(%0) \n" \ ++ " cache %1, 0x2c0(%0); cache %1, 0x2e0(%0) \n" \ ++ " cache %1, 0x300(%0); cache %1, 0x320(%0) \n" \ ++ " cache %1, 0x340(%0); cache %1, 0x360(%0) \n" \ ++ " cache %1, 0x380(%0); cache %1, 0x3a0(%0) \n" \ ++ " cache %1, 0x3c0(%0); cache %1, 0x3e0(%0) \n" \ ++ " .set pop \n" \ ++ : \ ++ : "r" (base), \ ++ "i" (op)); ++ ++void flush_cache_all(void) ++{ ++ unsigned long start = CKSEG0ADDR(0x80000000); ++ unsigned long end = start + MEM_SIZE_M * 1024 / 4; ++ unsigned long lsize = 32; ++ unsigned long addr; ++ ++ int i; ++ ++ for (i = 0; i < 4; i++) { ++ for (addr = start; addr < end; addr += lsize * 32) ++ cache32_unroll32(addr | i, 0x03); /* Index Writeback scache */ ++ } ++} +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/image/dbg.c linux-2.6.30.5/arch/mips/loongson/image/dbg.c +--- linux-2.6.30.5.orig/arch/mips/loongson/image/dbg.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/image/dbg.c 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,61 @@ ++/* serial port debug support */ ++ ++#ifdef SERIAL_PORT_DEBUG ++ ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++#define UART_BASE CKSEG1ADDR(LOONGSON_UART_BASE) ++ ++void putc(char c) ++{ ++ int timeout; ++ char reg; ++ ++ reg = *((char *)(UART_BASE + UART_LSR)) & UART_LSR_THRE; ++ for (timeout = 1024; reg == 0 && timeout > 0; timeout--) ++ reg = (*((char *)(UART_BASE + UART_LSR))) & UART_LSR_THRE; ++ ++ *((char *)(UART_BASE + UART_TX)) = c; ++} ++ ++void puts(const char *s) ++{ ++ char c; ++ while ((c = *s++) != '\0') { ++ putc(c); ++ if (c == '\n') ++ putc('\r'); ++ } ++} ++ ++void puthex(unsigned long val) ++{ ++ ++ unsigned char buf[10]; ++ int i; ++ for (i = 7; i >= 0; i--) { ++ buf[i] = "0123456789ABCDEF"[val & 0x0F]; ++ val >>= 4; ++ } ++ buf[8] = '\0'; ++ puts(buf); ++} ++#else ++void putc(char c) ++{ ++} ++ ++void puts(const char *s) ++{ ++} ++ ++void puthex(unsigned long val) ++{ ++} ++#endif +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/image/decompress.c linux-2.6.30.5/arch/mips/loongson/image/decompress.c +--- linux-2.6.30.5.orig/arch/mips/loongson/image/decompress.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/image/decompress.c 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,134 @@ ++/* ++ * Misc. bootloader code for many machines. ++ * ++ * Copyright 2001 MontaVista Software Inc. ++ * Author: Matt Porter Derived from ++ * arch/ppc/boot/prep/misc.c ++ * ++ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology ++ * Author: Wu Zhangjin ++ * ++ * 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 ++#include ++#include ++ ++/* These two variables specify the free mem region ++ * that can be used for temporary malloc area ++ * ++ * Here is toally 15M ++ */ ++#define FREE_MEM_START CKSEG0ADDR(0x83000000) ++#define FREE_MEM_END CKSEG0ADDR(0x83f00000) ++ ++unsigned long free_mem_ptr; ++unsigned long free_mem_end_ptr; ++char *zimage_start; ++ ++/* The linker tells us where the image is. */ ++extern unsigned char __image_begin, __image_end; ++extern unsigned char __ramdisk_begin, __ramdisk_end; ++unsigned long initrd_size; ++ ++/* debug interface via searil port */ ++extern void puts(const char *s); ++extern void puthex(unsigned long val); ++void error(char *x) ++{ ++ puts("\n\n"); ++ puts(x); ++ puts("\n\n -- System halted"); ++ ++ while (1) ++ ; /* Halt */ ++} ++ ++/* cache fulshing support */ ++extern void flush_cache_all(void); ++ ++/* gunzip declarations */ ++#define STATIC static ++ ++#ifdef CONFIG_KERNEL_GZIP ++#include "../../../../lib/decompress_inflate.c" ++#elif defined(CONFIG_KERNEL_BZIP2) ++#include "../../../../lib/decompress_bunzip2.c" ++#elif defined(CONFIG_KERNEL_LZMA) ++#include "../../../../lib/decompress_unlzma.c" ++#endif ++ ++void decompress_kernel(unsigned long load_addr, int num_words, ++ unsigned long cksum, unsigned long *sp) ++{ ++ extern unsigned long start; ++ int zimage_size; ++ ++ initrd_size = (unsigned long)(&__ramdisk_end) - ++ (unsigned long)(&__ramdisk_begin); ++ ++ /* ++ * Reveal where we were loaded at and where we ++ * were relocated to. ++ */ ++ puts("loaded at: "); ++ puthex(load_addr); ++ puts(" "); ++ puthex((unsigned long)(load_addr + (4 * num_words))); ++ puts("\n"); ++ if ((unsigned long)load_addr != (unsigned long)&start) { ++ puts("relocated to: "); ++ puthex((unsigned long)&start); ++ puts(" "); ++ puthex((unsigned long)((unsigned long)&start + ++ (4 * num_words))); ++ puts("\n"); ++ } ++ ++ /* ++ * We link ourself to an arbitrary low address. When we run, we ++ * relocate outself to that address. __image_beign points to ++ * the part of the image where the zImage is. -- Tom ++ */ ++ zimage_start = (char *)(unsigned long)(&__image_begin); ++ zimage_size = (unsigned long)(&__image_end) - ++ (unsigned long)(&__image_begin); ++ ++ /* ++ * The zImage and initrd will be between start and _end, so they've ++ * already been moved once. We're good to go now. -- Tom ++ */ ++ puts("zimage at: "); ++ puthex((unsigned long)zimage_start); ++ puts(" "); ++ puthex((unsigned long)(zimage_size + zimage_start)); ++ puts("\n"); ++ ++ if (initrd_size) { ++ puts("initrd at: "); ++ puthex((unsigned long)(&__ramdisk_begin)); ++ puts(" "); ++ puthex((unsigned long)(&__ramdisk_end)); ++ puts("\n"); ++ } ++ ++ /* assume the chunk below 8M is free */ ++ free_mem_ptr = FREE_MEM_START; ++ free_mem_end_ptr = FREE_MEM_END; ++ ++ /* Display standard Linux/MIPS boot prompt for kernel args */ ++ puts("Uncompressing Linux at load address "); ++ puthex(VMLINUX_LOAD_ADDRESS); ++ puts("\n"); ++ /* I don't like this hard coded gunzip size (fixme) */ ++ decompress(zimage_start, zimage_size, 0, 0, ++ (void *)VMLINUX_LOAD_ADDRESS, 0, error); ++#if 1 ++ flush_cache_all(); ++#endif ++ puts("Now, booting the kernel...\n"); ++} +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/image/dummy.c linux-2.6.30.5/arch/mips/loongson/image/dummy.c +--- linux-2.6.30.5.orig/arch/mips/loongson/image/dummy.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/image/dummy.c 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,4 @@ ++int main(void) ++{ ++ return 0; ++} +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/image/head.S linux-2.6.30.5/arch/mips/loongson/image/head.S +--- linux-2.6.30.5.orig/arch/mips/loongson/image/head.S 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/image/head.S 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,100 @@ ++/* ++ * arch/mips/kernel/head.S ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Copyright (C) 1994, 1995 Waldorf Electronics ++ * Written by Ralf Baechle and Andreas Busse ++ * Copyright (C) 1995 - 1999 Ralf Baechle ++ * Copyright (C) 1996 Paul M. Antoine ++ * Modified for DECStation and hence R3000 support by Paul M. Antoine ++ * Further modifications by David S. Miller and Harald Koerfgen ++ * Copyright (C) 1999 Silicon Graphics, Inc. ++ * ++ * Head.S contains the MIPS exception handler and startup code. ++ * ++ ************************************************************************** ++ * 9 Nov, 2000. ++ * Added Cache Error exception handler and SBDDP EJTAG debug exception. ++ * ++ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com ++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. ++ ************************************************************************** ++ */ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define IndexInvalidate_I 0x00 ++#define IndexWriteBack_D 0x01 ++ ++ .set noreorder ++ .cprestore ++ LEAF(start) ++start: ++ bal locate ++ nop ++locate: ++ subu s8, ra, 8 /* Where we were loaded */ ++ PTR_LA sp, (.stack + 8192) ++ ++ move s0, a0 /* Save boot rom start args */ ++ move s1, a1 ++ move s2, a2 ++ move s3, a3 ++ ++ PTR_LA a0, start /* Where we were linked to run */ ++ ++ move a1, s8 ++ PTR_LA a2, _edata ++ subu t1, a2, a0 ++ srl t1, t1, 2 ++ ++ /* copy text section */ ++ li t0, 0 ++1: lw v0, 0(a1) ++ nop ++ sw v0, 0(a0) ++ xor t0, t0, v0 ++ addu a0, 4 ++ bne a2, a0, 1b ++ addu a1, 4 ++ ++ /* Clear BSS */ ++ PTR_LA a0, _edata ++ PTR_LA a2, _end ++2: sw zero, 0(a0) ++ bne a2, a0, 2b ++ addu a0, 4 ++ ++ move a0, s8 /* load address */ ++ move a1, t1 /* length in words */ ++ move a2, t0 /* checksum */ ++ move a3, sp ++ ++ PTR_LA ra, 1f ++ PTR_LA k0, decompress_kernel ++ jr k0 ++ nop ++1: ++ ++ move a0, s0 ++ move a1, s1 ++ move a2, s2 ++ move a3, s3 ++ li k0, KERNEL_ENTRY ++ jr k0 ++ nop ++3: ++ b 3b ++ END(start) ++ ++ .comm .stack,4096*2,4 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/image/ld.script linux-2.6.30.5/arch/mips/loongson/image/ld.script +--- linux-2.6.30.5.orig/arch/mips/loongson/image/ld.script 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/image/ld.script 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,152 @@ ++OUTPUT_ARCH(mips) ++ENTRY(start) ++SECTIONS ++{ ++ /* Read-only sections, merged into text segment: */ ++ /* . = 0x81000000; */ /* 32bit */ ++ /* . = 0xffffffff81000000; */ /* 64bit */ ++ .init : { *(.init) } =0 ++ .text : ++ { ++ _ftext = . ; ++ *(.text) ++ *(.rodata) ++ *(.rodata1) ++ /* .gnu.warning sections are handled specially by elf32.em. */ ++ *(.gnu.warning) ++ } =0 ++ .kstrtab : { *(.kstrtab) } ++ ++ . = ALIGN(16); /* Exception table */ ++ __start___ex_table = .; ++ __ex_table : { *(__ex_table) } ++ __stop___ex_table = .; ++ ++ __start___dbe_table = .; /* Exception table for data bus errors */ ++ __dbe_table : { *(__dbe_table) } ++ __stop___dbe_table = .; ++ ++ __start___ksymtab = .; /* Kernel symbol table */ ++ __ksymtab : { *(__ksymtab) } ++ __stop___ksymtab = .; ++ ++ _etext = .; ++ ++ . = ALIGN(8192); ++ .data.init_task : { *(.data.init_task) } ++ ++ /* Startup code */ ++ . = ALIGN(4096); ++ __init_begin = .; ++ .text.init : { *(.text.init) } ++ .data.init : { *(.data.init) } ++ . = ALIGN(16); ++ __setup_start = .; ++ .setup.init : { *(.setup.init) } ++ __setup_end = .; ++ __initcall_start = .; ++ .initcall.init : { *(.initcall.init) } ++ __initcall_end = .; ++ . = ALIGN(4096); /* Align double page for init_task_union */ ++ __init_end = .; ++ ++ . = ALIGN(4096); ++ .data.page_aligned : { *(.data.idt) } ++ ++ . = ALIGN(32); ++ .data.cacheline_aligned : { *(.data.cacheline_aligned) } ++ ++ .fini : { *(.fini) } =0 ++ .reginfo : { *(.reginfo) } ++ /* Adjust the address for the data segment. We want to adjust up to ++ the same address within the page on the next page up. It would ++ be more correct to do this: ++ . = .; ++ The current expression does not correctly handle the case of a ++ text segment ending precisely at the end of a page; it causes the ++ data segment to skip a page. The above expression does not have ++ this problem, but it will currently (2/95) cause BFD to allocate ++ a single segment, combining both text and data, for this case. ++ This will prevent the text segment from being shared among ++ multiple executions of the program; I think that is more ++ important than losing a page of the virtual address space (note ++ that no actual memory is lost; the page which is skipped can not ++ be referenced). */ ++ . = .; ++ .data : ++ { ++ _fdata = . ; ++ *(.data) ++ ++ /* Put the compressed image here, so bss is on the end. */ ++ __image_begin = .; ++ *(.image) ++ __image_end = .; ++ /* Align the initial ramdisk image (INITRD) on page boundaries. */ ++ . = ALIGN(4096); ++ __ramdisk_begin = .; ++ *(.initrd) ++ __ramdisk_end = .; ++ . = ALIGN(4096); ++ ++ CONSTRUCTORS ++ } ++ .data1 : { *(.data1) } ++ _gp = . + 0x8000; ++ .lit8 : { *(.lit8) } ++ .lit4 : { *(.lit4) } ++ .ctors : { *(.ctors) } ++ .dtors : { *(.dtors) } ++ .got : { *(.got.plt) *(.got) } ++ .dynamic : { *(.dynamic) } ++ /* We want the small data sections together, so single-instruction offsets ++ can access them all, and initialized data all before uninitialized, so ++ we can shorten the on-disk segment size. */ ++ .sdata : { *(.sdata) } ++ . = ALIGN(4); ++ _edata = .; ++ PROVIDE (edata = .); ++ ++ __bss_start = .; ++ _fbss = .; ++ .sbss : { *(.sbss) *(.scommon) } ++ .bss : ++ { ++ *(.dynbss) ++ *(.bss) ++ *(COMMON) ++ . = ALIGN(4); ++ _end = . ; ++ PROVIDE (end = .); ++ } ++ ++ /* Sections to be discarded */ ++ /DISCARD/ : ++ { ++ *(.text.exit) ++ *(.data.exit) ++ *(.exitcall.exit) ++ } ++ ++ /* This is the MIPS specific mdebug section. */ ++ .mdebug : { *(.mdebug) } ++ /* These are needed for ELF backends which have not yet been ++ converted to the new style linker. */ ++ .stab 0 : { *(.stab) } ++ .stabstr 0 : { *(.stabstr) } ++ /* DWARF debug sections. ++ Symbols in the .debug DWARF section are relative to the beginning of the ++ section so we begin .debug at 0. It's not clear yet what needs to happen ++ for the others. */ ++ .debug 0 : { *(.debug) } ++ .debug_srcinfo 0 : { *(.debug_srcinfo) } ++ .debug_aranges 0 : { *(.debug_aranges) } ++ .debug_pubnames 0 : { *(.debug_pubnames) } ++ .debug_sfnames 0 : { *(.debug_sfnames) } ++ .line 0 : { *(.line) } ++ /* These must appear regardless of . */ ++ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } ++ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } ++ .comment : { *(.comment) } ++ .note : { *(.note) } ++} +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/image/Makefile linux-2.6.30.5/arch/mips/loongson/image/Makefile +--- linux-2.6.30.5.orig/arch/mips/loongson/image/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/image/Makefile 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,61 @@ ++# ++# arch/mips/zboot/Makefile ++# ++# This file is subject to the terms and conditions of the GNU General Public ++# License. See the file "COPYING" in the main directory of this archive ++# for more details. ++ ++# Adapted for MIPS Pete Popov, Dan Malek ++# ++# Copyright (C) 1994 by Linus Torvalds ++# Adapted for PowerPC by Gary Thomas ++# modified by Cort (cort@cs.nmt.edu) ++# ++# Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology ++# Author: Wu Zhangjin ++# ++ ++# Assume you have at least a 256M memory, this is used in cache.c ++KBUILD_CFLAGS := $(LINUXINCLUDE) $(KBUILD_CFLAGS) -D__KERNEL__ -DMEM_SIZE_M=256 -DSERIAL_PORT_DEBUG ++KBUILD_AFLAGS := $(LINUXINCLUDE) $(KBUILD_AFLAGS) -D__ASSEMBLY__ \ ++ -DKERNEL_ENTRY=0x$(shell $(NM) $(objtree)/$(KBUILD_IMAGE) | grep kernel_entry | cut -f1 -d \ ) ++ ++OBJECTS := $(obj)/head.o $(obj)/decompress.o $(obj)/mem.o $(obj)/cache.o $(obj)/dbg.o ++ ++OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S ++$(obj)/vmlinux.bin: $(KBUILD_IMAGE) ++ $(call if_changed,objcopy) ++ ++suffix_$(CONFIG_KERNEL_GZIP) = gz ++suffix_$(CONFIG_KERNEL_BZIP2) = bz2 ++suffix_$(CONFIG_KERNEL_LZMA) = lzma ++tool_$(CONFIG_KERNEL_GZIP) = gzip ++tool_$(CONFIG_KERNEL_BZIP2) = bzip2 ++tool_$(CONFIG_KERNEL_LZMA) = lzma ++$(obj)/vmlinux.$(suffix_y): $(obj)/vmlinux.bin ++ $(call if_changed,$(tool_y)) ++ ++$(obj)/piggy.o: $(obj)/vmlinux.$(suffix_y) $(obj)/dummy.o ++ $(Q)$(OBJCOPY) $(OBJCOPYFLAGS) \ ++ --add-section=.image=$< \ ++ --set-section-flags=.image=contents,alloc,load,readonly,data \ ++ $(obj)/dummy.o $@ ++ ++# The start address of the compressed kernel, Z_KERNEL_START > KERNEL_START + KERNEL_SIZE ++LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext 0x$(if $(CONFIG_64BIT),ffffffff,)81000000 -T ++$(obj)/vmlinuz: $(src)/ld.script $(OBJECTS) $(obj)/piggy.o ++ $(call if_changed,ld) ++ ++OBJCOPYFLAGS_zImage := $(OBJCOPYFLAGS) -R .comment -R .stab -R .stabstr -R .initrd -R .sysmap ++$(obj)/zImage: $(obj)/vmlinuz ++ $(call if_changed,objcopy) ++ ++zImage: $(obj)/zImage ++ $(Q)ln -sf $< $(objtree)/vmlinuz ++ $(Q)echo " SYMLINK $(objtree)/"vmlinuz ++ ++clean: ++clean-files += *.o \ ++ zImage* \ ++ vmlinu* \ ++ $(objtree)/vmlinuz +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/image/mem.c linux-2.6.30.5/arch/mips/loongson/image/mem.c +--- linux-2.6.30.5.orig/arch/mips/loongson/image/mem.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/image/mem.c 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,24 @@ ++/* memory opernation support */ ++ ++#include ++ ++void *memset(void *s, int c, size_t n) ++{ ++ int i; ++ char *ss = s; ++ ++ for (i = 0; i < n; i++) ++ ss[i] = c; ++ return s; ++} ++ ++void *memcpy(void *dest, const void *src, size_t n) ++{ ++ int i; ++ const char *s = src; ++ char *d = dest; ++ ++ for (i = 0; i < n; i++) ++ d[i] = s[i]; ++ return dest; ++} +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/Kconfig linux-2.6.30.5/arch/mips/loongson/Kconfig +--- linux-2.6.30.5.orig/arch/mips/loongson/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/Kconfig 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,136 @@ +choice + prompt "Machine Type" + depends on MACH_LOONGSON @@ -16167,6 +16415,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/Kconfig linux-2.6.30/arch/mips/lo + select SYS_HAS_MACH_PROM_INIT_CMDLINE + select GENERIC_HARDIRQS_NO__DO_IRQ + select GENERIC_ISA_DMA_SUPPORT_BROKEN ++ select EC_KB3310B if PM + select CPU_HAS_WB + select CS5536 + help @@ -16220,9 +16469,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/Kconfig linux-2.6.30/arch/mips/lo + other peripheral spaces not. + + Specify a zeroed size to disable this feature. -diff -Nur linux-2.6.30.orig/arch/mips/loongson/Makefile linux-2.6.30/arch/mips/loongson/Makefile ---- linux-2.6.30.orig/arch/mips/loongson/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/Makefile 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/Makefile linux-2.6.30.5/arch/mips/loongson/Makefile +--- linux-2.6.30.5.orig/arch/mips/loongson/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/Makefile 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,23 @@ +# +# Common code for all Loongson based systems @@ -16247,9 +16496,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/Makefile linux-2.6.30/arch/mips/l +# + +obj-$(CONFIG_LEMOTE_YEELOONG2F) += yeeloong-2f/ -diff -Nur linux-2.6.30.orig/arch/mips/loongson/yeeloong-2f/init.c linux-2.6.30/arch/mips/loongson/yeeloong-2f/init.c ---- linux-2.6.30.orig/arch/mips/loongson/yeeloong-2f/init.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/yeeloong-2f/init.c 2009-06-14 20:26:27.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/yeeloong-2f/init.c linux-2.6.30.5/arch/mips/loongson/yeeloong-2f/init.c +--- linux-2.6.30.5.orig/arch/mips/loongson/yeeloong-2f/init.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/yeeloong-2f/init.c 2009-08-22 13:41:28.000000000 +0200 @@ -0,0 +1,80 @@ +/* + * board specific init routines @@ -16281,7 +16530,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/yeeloong-2f/init.c linux-2.6.30/a + _wrmsr(USB_MSR_REG(USB_CONFIG), 0x4, 0xBF000); + + if (strstr(arcs_cmdline, "no_auto_cmd") == NULL) { -+ unsigned char default_root[50] = "/dev/hda1"; ++ unsigned char default_root[50] = "/dev/sda1"; + char *pmon_ver, *ec_ver, *p, version[60], ec_version[64]; + + p = arcs_cmdline; @@ -16331,9 +16580,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/yeeloong-2f/init.c linux-2.6.30/a + && (strstr(arcs_cmdline, "7inch") != NULL)) + strcat(arcs_cmdline, " vga=800x480x16"); +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/yeeloong-2f/irq.c linux-2.6.30/arch/mips/loongson/yeeloong-2f/irq.c ---- linux-2.6.30.orig/arch/mips/loongson/yeeloong-2f/irq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/yeeloong-2f/irq.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/yeeloong-2f/irq.c linux-2.6.30.5/arch/mips/loongson/yeeloong-2f/irq.c +--- linux-2.6.30.5.orig/arch/mips/loongson/yeeloong-2f/irq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/yeeloong-2f/irq.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology @@ -16388,29 +16637,360 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/yeeloong-2f/irq.c linux-2.6.30/ar + LOONGSON_INTPOL = LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1; + LOONGSON_INTEDGE &= ~(LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1); +} -diff -Nur linux-2.6.30.orig/arch/mips/loongson/yeeloong-2f/Makefile linux-2.6.30/arch/mips/loongson/yeeloong-2f/Makefile ---- linux-2.6.30.orig/arch/mips/loongson/yeeloong-2f/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/yeeloong-2f/Makefile 2009-06-14 20:25:19.000000000 +0200 -@@ -0,0 +1,5 @@ +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/yeeloong-2f/Makefile linux-2.6.30.5/arch/mips/loongson/yeeloong-2f/Makefile +--- linux-2.6.30.5.orig/arch/mips/loongson/yeeloong-2f/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/yeeloong-2f/Makefile 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,11 @@ +# +# Makefile for fuloong-2f +# + +obj-y += init.o irq.o reset.o -diff -Nur linux-2.6.30.orig/arch/mips/loongson/yeeloong-2f/reset.c linux-2.6.30/arch/mips/loongson/yeeloong-2f/reset.c ---- linux-2.6.30.orig/arch/mips/loongson/yeeloong-2f/reset.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/loongson/yeeloong-2f/reset.c 2009-06-14 20:25:19.000000000 +0200 -@@ -0,0 +1,91 @@ -+/* Board-specific reboot/shutdown routines -+ * Copyright (c) 2009 Philippe Vachon ++ ++# ++# Power Management Support ++# ++ ++obj-$(CONFIG_PM) += pm.o +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/yeeloong-2f/pm.c linux-2.6.30.5/arch/mips/loongson/yeeloong-2f/pm.c +--- linux-2.6.30.5.orig/arch/mips/loongson/yeeloong-2f/pm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/yeeloong-2f/pm.c 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,321 @@ ++/* ++ * loongson-specific STR/Standby + * -+ * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology -+ * Author: Wu Zhangjin, wuzj@lemote.com ++ * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology ++ * Author: Wu Zhangjin + * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. ++ * This program is 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 ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#ifdef CONFIG_CS5536_MFGPT ++#include ++#endif ++ ++#include "../../../../drivers/platform/loongson/ec_kb3310b/ec.h" ++#include "../../../../drivers/platform/loongson/ec_kb3310b/ec_misc_fn.h" ++ ++/* debug functions */ ++extern void prom_printf(char *fmt, ...); ++ ++/* i8042 keyboard operations: drivers/input/serio/i8042.c */ ++extern int i8042_enable_kbd_port(void); ++extern void i8042_flush(void); ++ ++static unsigned int cached_master_mask; /* i8259A */ ++static unsigned int cached_slave_mask; ++static unsigned int cached_bonito_irq_mask; /* bonito */ ++ ++void arch_suspend_enable_irqs(void) ++{ ++ /* enable all mips interrupts */ ++ local_irq_enable(); ++ ++ /* only enable the cached interrupts of i8259A */ ++ outb(cached_slave_mask, PIC_SLAVE_IMR); ++ outb(cached_master_mask, PIC_MASTER_IMR); ++ ++ /* enable all cached interrupts of bonito */ ++ LOONGSON_INTENSET = cached_bonito_irq_mask; ++ (void)LOONGSON_INTENSET; ++ mmiowb(); ++} ++ ++void arch_suspend_disable_irqs(void) ++{ ++ /* disable all mips interrupts */ ++ local_irq_disable(); ++ ++ /* disable all interrupts of i8259A */ ++ cached_slave_mask = inb(PIC_SLAVE_IMR); ++ cached_master_mask = inb(PIC_MASTER_IMR); ++ ++ outb(0xff, PIC_SLAVE_IMR); ++ inb(PIC_SLAVE_IMR); ++ outb(0xff, PIC_MASTER_IMR); ++ inb(PIC_MASTER_IMR); ++ ++ /* disable all interrupts of bonito */ ++ cached_bonito_irq_mask = LOONGSON_INTEN; ++ LOONGSON_INTENCLR = 0xffff; ++ (void)LOONGSON_INTENCLR; ++ mmiowb(); ++} ++ ++#define I8042_KBD_IRQ 1 ++#define SCI_IRQ_NUM 0x0A /* system control interface */ ++ ++/* i8042, sci are connnectted to i8259A */ ++static void setup_wakeup_interrupt(void) ++{ ++ int irq_mask; ++ ++ /* open the keyboard irq in i8259A */ ++ outb((0xff & ~(1 << I8042_KBD_IRQ)), PIC_MASTER_IMR); ++ irq_mask = inb(PIC_MASTER_IMR); ++ /* enable keyboard port */ ++ i8042_enable_kbd_port(); ++ ++ /* there is a need to wakeup the cpu via sci interrupt with relative ++ * lid openning event ++ */ ++ outb(irq_mask & ~(1 << (SCI_IRQ_NUM - 8)), PIC_MASTER_IMR); ++ inb(PIC_MASTER_IMR); ++ outb(0xff & ~(1 << (SCI_IRQ_NUM - 8)), PIC_SLAVE_IMR); ++ inb(PIC_SLAVE_IMR); ++} ++ ++extern int ec_query_seq(unsigned char cmd); ++extern int sci_get_event_num(void); ++ ++static int wakeup_loongson(void) ++{ ++ int irq; ++ ++ /* query the interrupt number */ ++ irq = mach_i8259_irq(); ++ if (irq < 0) ++ return 0; ++ prom_printf("irq = %d\n", irq); ++ ++ if (irq == I8042_KBD_IRQ) ++ return 1; ++ else if (irq == SCI_IRQ_NUM) { ++ int ret, sci_event; ++ /* query the event number */ ++ ret = ec_query_seq(CMD_GET_EVENT_NUM); ++ if (ret < 0) ++ return 0; ++ sci_event = sci_get_event_num(); ++ prom_printf("sci event = %d\n", sci_event); ++ if (sci_event < 0) ++ return 0; ++ if (sci_event == SCI_EVENT_NUM_LID) { ++ int lid_status; ++ /* check the LID status */ ++ lid_status = ec_read(REG_LID_DETECT); ++ prom_printf("lid status = %d\n", lid_status); ++ /* wakeup cpu when people open the LID */ ++ if (lid_status == BIT_LID_DETECT_ON) ++ return 1; ++ } ++ } ++ return 0; ++} ++ ++static void wait_for_wakeup_events(void) ++{ ++wait: ++ if (!wakeup_loongson()) { ++ LOONGSON_CHIPCFG0 &= ~0x7; ++ goto wait; ++ } ++} ++ ++/* stop all perf counters by default ++ * $24 is the control register of loongson perf counter ++ */ ++static inline void stop_perf_counters(void) ++{ ++ __write_64bit_c0_register($24, 0, 0); ++} ++ ++ ++static void loongson_suspend_enter(void) ++{ ++ static unsigned int cached_cpu_freq; ++ ++ prom_printf("suspend: try to setup the wakeup interrupt (keyboard interrupt)\n"); ++ setup_wakeup_interrupt(); ++ ++ /* stop all perf counters */ ++ stop_perf_counters(); ++ ++ cached_cpu_freq = LOONGSON_CHIPCFG0; ++ ++ /* handle the old delayed kbd interrupt */ ++ LOONGSON_CHIPCFG0 &= ~0x7; /* Put CPU into wait mode */ ++ i8042_flush(); ++ ++ /* handle the real wakeup interrupt */ ++ LOONGSON_CHIPCFG0 &= ~0x7; ++ mmiowb(); ++ ++ /* if the events are really what we want to wakeup cpu, wake up it, ++ * otherwise, we Put CPU into wait mode again. ++ */ ++ prom_printf("suspend: here we wait for several events to wake up cpu\n"); ++ wait_for_wakeup_events(); ++ ++ LOONGSON_CHIPCFG0 = cached_cpu_freq; ++ mmiowb(); ++} ++ ++static unsigned int cached_camera_status; ++static unsigned int cached_mute_status; ++ ++static void mach_suspend(void) ++{ ++ unsigned int value; ++ ++ /* LCD backlight off */ ++ ec_write(REG_BACKLIGHT_CTRL, BIT_BACKLIGHT_OFF); ++ ++ /* close lcd output */ ++ outb(0x31, 0x3c4); ++ value = inb(0x3c5); ++ value = (value & 0xf8) | 0x02; ++ outb(0x31, 0x3c4); ++ outb(value, 0x3c5); ++ ++ /* close vga output */ ++ outb(0x21, 0x3c4); ++ value = inb(0x3c5); ++ value |= (1 << 7); ++ outb(0x21, 0x3c4); ++ outb(value, 0x3c5); ++ ++ /* poweroff three usb ports */ ++ ec_write(0xf461, 0x00); ++ ec_write(0xf462, 0x00); ++ ec_write(0xf463, 0x00); ++ ++ /* poweroff camera */ ++ cached_camera_status = ec_read(REG_CAMERA_STATUS); ++ if (cached_camera_status) { ++ value = ec_read(REG_CAMERA_CONTROL); ++ ec_write(REG_CAMERA_CONTROL, value | (1 << 1)); ++ } ++ ++ /* MUTE */ ++ cached_mute_status = ec_read(REG_AUDIO_MUTE); ++ ec_write(REG_AUDIO_MUTE, BIT_AUDIO_MUTE_ON); ++ ++ /* minimize the speed of FAN */ ++ ec_write(0xf459, 1); /* change the fan to manual mode */ ++ ec_write(0xf4cc, 1); /* change the speed to the lowest one, not turn it off */ ++ ++#ifdef CONFIG_CS5536_MFGPT ++ /* stop counting of cs5536 mfgpt timer */ ++ outw(inw(MFGPT0_SETUP) | (1 << 11) , MFGPT0_SETUP); ++#endif ++} ++ ++static void mach_resume(void) ++{ ++ unsigned int value; ++ ++ /* LCD backlight on */ ++ ec_write(REG_BACKLIGHT_CTRL, BIT_BACKLIGHT_ON); ++ ++ /* open lcd output */ ++ outb(0x31, 0x3c4); ++ value = inb(0x3c5); ++ value = (value & 0xf8) | 0x03; ++ outb(0x31, 0x3c4); ++ outb(value, 0x3c5); ++ ++ /* open vga output */ ++ outb(0x21, 0x3c4); ++ value = inb(0x3c5); ++ value &= ~(1 << 7); ++ outb(0x21, 0x3c4); ++ outb(value, 0x3c5); ++ ++ /* there is a need to enable the bonito interrupt here to fix the ++ * problem of powering on usb ports */ ++ LOONGSON_INTENSET = cached_bonito_irq_mask; ++ (void)LOONGSON_INTENSET; ++ mmiowb(); ++ /* power on three usb ports */ ++ ec_write(0xf461, 0x01); ++ ec_write(0xf462, 0x01); ++ ec_write(0xf463, 0x01); ++ ++ /* resume camera */ ++ ec_write(REG_CAMERA_CONTROL, cached_camera_status); ++ ++ /* resume the status of mute */ ++ ec_write(REG_AUDIO_MUTE, cached_mute_status); ++ ++ /* resume FAN */ ++ ec_write(0xf459, 0); /* change the fan to auto mode */ ++ ++#ifdef CONFIG_CS5536_MFGPT ++ /* enable counting of cs5536 mfgpt timer */ ++ outw(inw(MFGPT0_SETUP) & ~(1 << 11) , MFGPT0_SETUP); ++#endif ++} ++ ++static int loongson_pm_enter(suspend_state_t state) ++{ ++ prom_printf("suspend: try to call mach specific suspend\n"); ++ mach_suspend(); ++ ++ prom_printf("suspend: Enter into the wait mode of loongson cpu\n"); ++ loongson_suspend_enter(); ++ prom_printf("resume: waked up from wait mode of loongson cpu\n"); ++ ++ mach_resume(); ++ prom_printf("resume: return from mach specific resume\n"); ++ ++ return 0; ++} ++ ++static int loongson_pm_valid_state(suspend_state_t state) ++{ ++ switch (state) { ++ case PM_SUSPEND_ON: ++ case PM_SUSPEND_STANDBY: ++ case PM_SUSPEND_MEM: ++ return 1; ++ ++ default: ++ return 0; ++ } ++} ++ ++static struct platform_suspend_ops loongson_pm_ops = { ++ .valid = loongson_pm_valid_state, ++ .enter = loongson_pm_enter, ++}; ++ ++static int __init loongson_pm_init(void) ++{ ++ suspend_set_ops(&loongson_pm_ops); ++ ++ return 0; ++} ++arch_initcall(loongson_pm_init); +diff -Nur linux-2.6.30.5.orig/arch/mips/loongson/yeeloong-2f/reset.c linux-2.6.30.5/arch/mips/loongson/yeeloong-2f/reset.c +--- linux-2.6.30.5.orig/arch/mips/loongson/yeeloong-2f/reset.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/loongson/yeeloong-2f/reset.c 2009-08-21 21:18:06.000000000 +0200 +@@ -0,0 +1,91 @@ ++/* Board-specific reboot/shutdown routines ++ * Copyright (c) 2009 Philippe Vachon ++ * ++ * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology ++ * Author: Wu Zhangjin, wuzj@lemote.com ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. + */ + +#include @@ -16492,9 +17072,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/loongson/yeeloong-2f/reset.c linux-2.6.30/ + } else + printk(KERN_INFO "you can shutdown the power safely now!\n"); +} -diff -Nur linux-2.6.30.orig/arch/mips/Makefile linux-2.6.30/arch/mips/Makefile ---- linux-2.6.30.orig/arch/mips/Makefile 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/Makefile 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/Makefile linux-2.6.30.5/arch/mips/Makefile +--- linux-2.6.30.5.orig/arch/mips/Makefile 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/Makefile 2009-08-21 21:17:59.000000000 +0200 @@ -120,7 +120,14 @@ cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap @@ -16504,20 +17084,24 @@ diff -Nur linux-2.6.30.orig/arch/mips/Makefile linux-2.6.30/arch/mips/Makefile +# only gcc >= 4.4 have the loongson-specific support +cflags-$(CONFIG_CPU_LOONGSON2) += -Wa,--trap +cflags-$(CONFIG_CPU_LOONGSON2E) += \ -+ $(call cc-option,-march=loongson2e,-march=r4600) $(call cc-option,-mtune=loongson2e) ++ $(call cc-option,-march=loongson2e,-march=r4600) +cflags-$(CONFIG_CPU_LOONGSON2F) += \ -+ $(call cc-option,-march=loongson2f,-march=r4600) $(call cc-optoin,-mtune=loongson2f) ++ $(call cc-option,-march=loongson2f,-march=r4600) + cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ -Wa,-mips32 -Wa,--trap cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ -@@ -307,9 +314,12 @@ +@@ -305,11 +312,15 @@ + load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 + # - # lemote fulong mini-PC board +-# lemote fulong mini-PC board ++# loongson family machines # -core-$(CONFIG_LEMOTE_FULONG) +=arch/mips/lemote/lm2e/ -load-$(CONFIG_LEMOTE_FULONG) +=0xffffffff80100000 -cflags-$(CONFIG_LEMOTE_FULONG) += -I$(srctree)/arch/mips/include/asm/mach-lemote ++all-$(CONFIG_MACH_LOONGSON) += zImage +core-$(CONFIG_MACH_LOONGSON) +=arch/mips/loongson/ +cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson \ + -mno-branch-likely @@ -16527,19 +17111,40 @@ diff -Nur linux-2.6.30.orig/arch/mips/Makefile linux-2.6.30/arch/mips/Makefile # # MIPS Malta board -@@ -675,6 +685,9 @@ - - drivers-$(CONFIG_OPROFILE) += arch/mips/oprofile/ +@@ -680,6 +691,11 @@ + $(Q)$(MAKE) $(build)=arch/mips/lasat/image $@ + endif -+# suspend and hibernation support -+drivers-$(CONFIG_PM) += arch/mips/power/ ++ifdef CONFIG_MACH_LOONGSON ++zImage: vmlinux ++ $(Q)$(MAKE) $(build)=arch/mips/loongson/image $@ ++endif + - ifdef CONFIG_LASAT - rom.bin rom.sw: vmlinux - $(Q)$(MAKE) $(build)=arch/mips/lasat/image $@ -diff -Nur linux-2.6.30.orig/arch/mips/oprofile/common.c linux-2.6.30/arch/mips/oprofile/common.c ---- linux-2.6.30.orig/arch/mips/oprofile/common.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/oprofile/common.c 2009-06-14 20:25:19.000000000 +0200 + # + # Some machines like the Indy need 32-bit ELF binaries for booting purposes. + # Other need ECOFF, so we build a 32-bit ELF binary for them which we then +@@ -728,6 +744,7 @@ + + archclean: + @$(MAKE) $(clean)=arch/mips/boot ++ @$(MAKE) $(clean)=arch/mips/loongson/image + @$(MAKE) $(clean)=arch/mips/lasat + + define archhelp +diff -Nur linux-2.6.30.5.orig/arch/mips/mm/uasm.c linux-2.6.30.5/arch/mips/mm/uasm.c +--- linux-2.6.30.5.orig/arch/mips/mm/uasm.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/mm/uasm.c 2009-08-21 21:18:06.000000000 +0200 +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include + #include +diff -Nur linux-2.6.30.5.orig/arch/mips/oprofile/common.c linux-2.6.30.5/arch/mips/oprofile/common.c +--- linux-2.6.30.5.orig/arch/mips/oprofile/common.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/oprofile/common.c 2009-08-21 21:18:06.000000000 +0200 @@ -16,6 +16,7 @@ extern struct op_mips_model op_model_mipsxx_ops __attribute__((weak)); @@ -16559,17 +17164,17 @@ diff -Nur linux-2.6.30.orig/arch/mips/oprofile/common.c linux-2.6.30/arch/mips/o }; if (!lmodel) -diff -Nur linux-2.6.30.orig/arch/mips/oprofile/Makefile linux-2.6.30/arch/mips/oprofile/Makefile ---- linux-2.6.30.orig/arch/mips/oprofile/Makefile 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/oprofile/Makefile 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/oprofile/Makefile linux-2.6.30.5/arch/mips/oprofile/Makefile +--- linux-2.6.30.5.orig/arch/mips/oprofile/Makefile 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/oprofile/Makefile 2009-08-21 21:18:06.000000000 +0200 @@ -15,3 +15,4 @@ oprofile-$(CONFIG_CPU_R10000) += op_model_mipsxx.o oprofile-$(CONFIG_CPU_SB1) += op_model_mipsxx.o oprofile-$(CONFIG_CPU_RM9000) += op_model_rm9000.o +oprofile-$(CONFIG_CPU_LOONGSON2) += op_model_loongson2.o -diff -Nur linux-2.6.30.orig/arch/mips/oprofile/op_model_loongson2.c linux-2.6.30/arch/mips/oprofile/op_model_loongson2.c ---- linux-2.6.30.orig/arch/mips/oprofile/op_model_loongson2.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/oprofile/op_model_loongson2.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/oprofile/op_model_loongson2.c linux-2.6.30.5/arch/mips/oprofile/op_model_loongson2.c +--- linux-2.6.30.5.orig/arch/mips/oprofile/op_model_loongson2.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/oprofile/op_model_loongson2.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,186 @@ +/* + * Loongson2 performance counter driver for oprofile @@ -16757,69 +17362,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/oprofile/op_model_loongson2.c linux-2.6.30 + .cpu_type = LOONGSON_CPU_TYPE, + .num_counters = 2 +}; -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-au1000.c linux-2.6.30/arch/mips/pci/fixup-au1000.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-au1000.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-au1000.c 2009-06-14 20:25:19.000000000 +0200 -@@ -31,7 +31,7 @@ - - extern char irq_tab_alchemy[][5]; - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - return irq_tab_alchemy[slot][pin]; - } -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-capcella.c linux-2.6.30/arch/mips/pci/fixup-capcella.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-capcella.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-capcella.c 2009-06-14 20:25:19.000000000 +0200 -@@ -38,7 +38,7 @@ - [14] = { -1, INTA, INTB, INTC, INTD } - }; - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - return irq_tab_capcella[slot][pin]; - } -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-cobalt.c linux-2.6.30/arch/mips/pci/fixup-cobalt.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-cobalt.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-cobalt.c 2009-06-14 20:25:19.000000000 +0200 -@@ -175,7 +175,7 @@ - [COBALT_PCICONF_ETH1] = ETH1_IRQ - }; - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - if (cobalt_board_id <= COBALT_BRD_ID_QUBE1) - return irq_tab_qube1[slot]; -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-emma2rh.c linux-2.6.30/arch/mips/pci/fixup-emma2rh.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-emma2rh.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-emma2rh.c 2009-06-14 20:25:19.000000000 +0200 -@@ -88,7 +88,7 @@ - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_EMMA2RH, - emma2rh_pci_host_fixup); - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - return irq_map[slot][pin]; - } -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-excite.c linux-2.6.30/arch/mips/pci/fixup-excite.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-excite.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-excite.c 2009-06-14 20:25:19.000000000 +0200 -@@ -21,7 +21,7 @@ - #include - #include - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - if (pin == 0) - return -1; -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-fuloong2e.c linux-2.6.30/arch/mips/pci/fixup-fuloong2e.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-fuloong2e.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/pci/fixup-fuloong2e.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/pci/fixup-fuloong2e.c linux-2.6.30.5/arch/mips/pci/fixup-fuloong2e.c +--- linux-2.6.30.5.orig/arch/mips/pci/fixup-fuloong2e.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/pci/fixup-fuloong2e.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,243 @@ +/* + * fixup-fuloong2e.c @@ -17064,33 +17609,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-fuloong2e.c linux-2.6.30/arch/mi + fuloong2e_686b_func5_fixup); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, + fuloong2e_nec_fixup); -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-ip32.c linux-2.6.30/arch/mips/pci/fixup-ip32.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-ip32.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-ip32.c 2009-06-14 20:25:19.000000000 +0200 -@@ -39,7 +39,7 @@ - * irqs. I suppose a device without a pin A will thank us for doing it - * right if there exists such a broken piece of crap. - */ --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - return irq_tab_mace[slot][pin]; - } -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-jmr3927.c linux-2.6.30/arch/mips/pci/fixup-jmr3927.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-jmr3927.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-jmr3927.c 2009-06-14 20:25:19.000000000 +0200 -@@ -31,7 +31,7 @@ - #include - #include - --int __init jmr3927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init jmr3927_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - unsigned char irq = pin; - -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-lemote2f.c linux-2.6.30/arch/mips/pci/fixup-lemote2f.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-lemote2f.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/pci/fixup-lemote2f.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/pci/fixup-lemote2f.c linux-2.6.30.5/arch/mips/pci/fixup-lemote2f.c +--- linux-2.6.30.5.orig/arch/mips/pci/fixup-lemote2f.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/pci/fixup-lemote2f.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2008 Lemote Technology @@ -17263,9 +17784,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-lemote2f.c linux-2.6.30/arch/mip + loongson_cs5536_ide_fixup); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, + loongson_nec_fixup); -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-lm2e.c linux-2.6.30/arch/mips/pci/fixup-lm2e.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-lm2e.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-lm2e.c 1970-01-01 01:00:00.000000000 +0100 +diff -Nur linux-2.6.30.5.orig/arch/mips/pci/fixup-lm2e.c linux-2.6.30.5/arch/mips/pci/fixup-lm2e.c +--- linux-2.6.30.5.orig/arch/mips/pci/fixup-lm2e.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/pci/fixup-lm2e.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,242 +0,0 @@ -/* - * fixup-lm2e.c @@ -17509,165 +18030,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-lm2e.c linux-2.6.30/arch/mips/pc - loongson2e_686b_func5_fixup); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, - loongson2e_nec_fixup); -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-malta.c linux-2.6.30/arch/mips/pci/fixup-malta.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-malta.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-malta.c 2009-06-14 20:25:19.000000000 +0200 -@@ -36,7 +36,7 @@ - {0, PCID, PCIA, PCIB, PCIC } /* 21: PCI Slot 4 */ - }; - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - int virq; - virq = irq_tab[slot][pin]; -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-mpc30x.c linux-2.6.30/arch/mips/pci/fixup-mpc30x.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-mpc30x.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-mpc30x.c 2009-06-14 20:25:19.000000000 +0200 -@@ -34,7 +34,7 @@ - [29] = MQ200_IRQ, - }; - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - if (slot == 30) - return internal_func_irqs[PCI_FUNC(dev->devfn)]; -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-pmcmsp.c linux-2.6.30/arch/mips/pci/fixup-pmcmsp.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-pmcmsp.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-pmcmsp.c 2009-06-14 20:25:19.000000000 +0200 -@@ -202,7 +202,7 @@ - * RETURNS: IRQ number - * - ****************************************************************************/ --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - #if !defined(CONFIG_PMC_MSP7120_GW) && !defined(CONFIG_PMC_MSP7120_EVAL) - printk(KERN_WARNING "PCI: unknown board, no PCI IRQs assigned.\n"); -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-pnx8550.c linux-2.6.30/arch/mips/pci/fixup-pnx8550.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-pnx8550.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-pnx8550.c 2009-06-14 20:25:19.000000000 +0200 -@@ -45,7 +45,7 @@ - /* nothing to do here */ - } - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - return pnx8550_irq_tab[slot][pin]; - } -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-rbtx4927.c linux-2.6.30/arch/mips/pci/fixup-rbtx4927.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-rbtx4927.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-rbtx4927.c 2009-06-14 20:25:19.000000000 +0200 -@@ -36,7 +36,7 @@ - #include - #include - --int __init rbtx4927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init rbtx4927_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - unsigned char irq = pin; - -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-rbtx4938.c linux-2.6.30/arch/mips/pci/fixup-rbtx4938.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-rbtx4938.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-rbtx4938.c 2009-06-14 20:25:19.000000000 +0200 -@@ -13,7 +13,7 @@ - #include - #include - --int __init rbtx4938_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init rbtx4938_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - int irq = tx4938_pcic1_map_irq(dev, slot); - -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-rc32434.c linux-2.6.30/arch/mips/pci/fixup-rc32434.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-rc32434.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-rc32434.c 2009-06-14 20:25:19.000000000 +0200 -@@ -37,7 +37,7 @@ - {0, 0, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3} - }; - --int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - int irq = 0; - -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-sni.c linux-2.6.30/arch/mips/pci/fixup-sni.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-sni.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-sni.c 2009-06-14 20:25:19.000000000 +0200 -@@ -130,7 +130,7 @@ - return (csmsr & 0xa0) == 0x20; - } - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - switch (sni_brd_type) { - case SNI_BRD_PCI_TOWER_CPLUS: -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-tb0219.c linux-2.6.30/arch/mips/pci/fixup-tb0219.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-tb0219.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-tb0219.c 2009-06-14 20:25:19.000000000 +0200 -@@ -23,7 +23,7 @@ - - #include - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - int irq = -1; - -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-tb0226.c linux-2.6.30/arch/mips/pci/fixup-tb0226.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-tb0226.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-tb0226.c 2009-06-14 20:25:19.000000000 +0200 -@@ -23,7 +23,7 @@ - #include - #include - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - int irq = -1; - -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-tb0287.c linux-2.6.30/arch/mips/pci/fixup-tb0287.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-tb0287.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-tb0287.c 2009-06-14 20:25:19.000000000 +0200 -@@ -22,7 +22,7 @@ - - #include - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - unsigned char bus; - int irq = -1; -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-wrppmc.c linux-2.6.30/arch/mips/pci/fixup-wrppmc.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-wrppmc.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-wrppmc.c 2009-06-14 20:25:19.000000000 +0200 -@@ -25,7 +25,7 @@ - [6] = {0, WRPPMC_PCI_INTA_IRQ, 0, 0, 0}, - }; - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - return pci_irq_tab[slot][pin]; - } -diff -Nur linux-2.6.30.orig/arch/mips/pci/fixup-yosemite.c linux-2.6.30/arch/mips/pci/fixup-yosemite.c ---- linux-2.6.30.orig/arch/mips/pci/fixup-yosemite.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/fixup-yosemite.c 2009-06-14 20:25:19.000000000 +0200 -@@ -26,7 +26,7 @@ - #include - #include - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - if (pin == 0) - return -1; -diff -Nur linux-2.6.30.orig/arch/mips/pci/Makefile linux-2.6.30/arch/mips/pci/Makefile ---- linux-2.6.30.orig/arch/mips/pci/Makefile 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/Makefile 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/pci/Makefile linux-2.6.30.5/arch/mips/pci/Makefile +--- linux-2.6.30.5.orig/arch/mips/pci/Makefile 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/pci/Makefile 2009-08-21 21:18:06.000000000 +0200 @@ -26,7 +26,9 @@ obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o @@ -17679,9 +18044,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/pci/Makefile linux-2.6.30/arch/mips/pci/Ma obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o -diff -Nur linux-2.6.30.orig/arch/mips/pci/ops-bonito64.c linux-2.6.30/arch/mips/pci/ops-bonito64.c ---- linux-2.6.30.orig/arch/mips/pci/ops-bonito64.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/ops-bonito64.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/pci/ops-bonito64.c linux-2.6.30.5/arch/mips/pci/ops-bonito64.c +--- linux-2.6.30.5.orig/arch/mips/pci/ops-bonito64.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/arch/mips/pci/ops-bonito64.c 2009-08-21 21:18:06.000000000 +0200 @@ -29,20 +29,16 @@ #define PCI_ACCESS_READ 0 #define PCI_ACCESS_WRITE 1 @@ -17737,9 +18102,9 @@ diff -Nur linux-2.6.30.orig/arch/mips/pci/ops-bonito64.c linux-2.6.30/arch/mips/ return -1; if (size == 1) -diff -Nur linux-2.6.30.orig/arch/mips/pci/ops-loongson2.c linux-2.6.30/arch/mips/pci/ops-loongson2.c ---- linux-2.6.30.orig/arch/mips/pci/ops-loongson2.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/pci/ops-loongson2.c 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/pci/ops-loongson2.c linux-2.6.30.5/arch/mips/pci/ops-loongson2.c +--- linux-2.6.30.5.orig/arch/mips/pci/ops-loongson2.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/pci/ops-loongson2.c 2009-08-21 21:18:06.000000000 +0200 @@ -0,0 +1,213 @@ +/* + * Copyright (C) 1999, 2000, 2004 MIPS Technologies, Inc. @@ -17954,107 +18319,14 @@ diff -Nur linux-2.6.30.orig/arch/mips/pci/ops-loongson2.c linux-2.6.30/arch/mips +} +EXPORT_SYMBOL(_wrmsr); +#endif -diff -Nur linux-2.6.30.orig/arch/mips/pci/pci-bcm1480.c linux-2.6.30/arch/mips/pci/pci-bcm1480.c ---- linux-2.6.30.orig/arch/mips/pci/pci-bcm1480.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/pci-bcm1480.c 2009-06-14 20:25:19.000000000 +0200 -@@ -74,7 +74,7 @@ - *(u32 *)(cfg_space + (addr & ~3)) = data; - } - --int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - if (pin == 0) - return -1; -diff -Nur linux-2.6.30.orig/arch/mips/pci/pci-bcm47xx.c linux-2.6.30/arch/mips/pci/pci-bcm47xx.c ---- linux-2.6.30.orig/arch/mips/pci/pci-bcm47xx.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/pci-bcm47xx.c 2009-06-14 20:25:19.000000000 +0200 -@@ -26,7 +26,7 @@ - #include - #include - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - return 0; - } -diff -Nur linux-2.6.30.orig/arch/mips/pci/pci-ip27.c linux-2.6.30/arch/mips/pci/pci-ip27.c ---- linux-2.6.30.orig/arch/mips/pci/pci-ip27.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/pci-ip27.c 2009-06-14 20:25:19.000000000 +0200 -@@ -141,7 +141,7 @@ - * A given PCI device, in general, should be able to intr any of the cpus - * on any one of the hubs connected to its xbow. - */ --int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - return 0; - } -diff -Nur linux-2.6.30.orig/arch/mips/pci/pci-lasat.c linux-2.6.30/arch/mips/pci/pci-lasat.c ---- linux-2.6.30.orig/arch/mips/pci/pci-lasat.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/pci-lasat.c 2009-06-14 20:25:19.000000000 +0200 -@@ -61,7 +61,7 @@ - #define LASAT_IRQ_PCIC (LASAT_IRQ_BASE + 7) - #define LASAT_IRQ_PCID (LASAT_IRQ_BASE + 8) - --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - switch (slot) { - case 1: -diff -Nur linux-2.6.30.orig/arch/mips/pci/pci-sb1250.c linux-2.6.30/arch/mips/pci/pci-sb1250.c ---- linux-2.6.30.orig/arch/mips/pci/pci-sb1250.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/pci-sb1250.c 2009-06-14 20:25:19.000000000 +0200 -@@ -84,7 +84,7 @@ - *(u32 *) (cfg_space + (addr & ~3)) = data; - } - --int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - return dev->irq; - } -diff -Nur linux-2.6.30.orig/arch/mips/pci/pci-tx4938.c linux-2.6.30/arch/mips/pci/pci-tx4938.c ---- linux-2.6.30.orig/arch/mips/pci/pci-tx4938.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/pci-tx4938.c 2009-06-14 20:25:19.000000000 +0200 -@@ -114,7 +114,7 @@ - return pciclk; - } - --int __init tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot) -+int __init tx4938_pcic1_map_irq(struct pci_dev *dev, u8 slot) - { - if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4938_pcic1ptr) { - switch (slot) { -diff -Nur linux-2.6.30.orig/arch/mips/pci/pci-tx4939.c linux-2.6.30/arch/mips/pci/pci-tx4939.c ---- linux-2.6.30.orig/arch/mips/pci/pci-tx4939.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/pci/pci-tx4939.c 2009-06-14 20:25:19.000000000 +0200 -@@ -50,7 +50,7 @@ - ((pciclk + 50000) / 100000) % 10); - } - --int __init tx4939_pcic1_map_irq(const struct pci_dev *dev, u8 slot) -+int __init tx4939_pcic1_map_irq(struct pci_dev *dev, u8 slot) - { - if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4939_pcic1ptr) { - switch (slot) { -@@ -70,7 +70,7 @@ - return -1; - } - --int __init tx4939_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init tx4939_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) - { - int irq = tx4939_pcic1_map_irq(dev, slot); - -diff -Nur linux-2.6.30.orig/arch/mips/power/cpu.c linux-2.6.30/arch/mips/power/cpu.c ---- linux-2.6.30.orig/arch/mips/power/cpu.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/power/cpu.c 2009-06-14 20:25:19.000000000 +0200 -@@ -0,0 +1,43 @@ +diff -Nur linux-2.6.30.5.orig/arch/mips/power/cpu.c linux-2.6.30.5/arch/mips/power/cpu.c +--- linux-2.6.30.5.orig/arch/mips/power/cpu.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/power/cpu.c 2009-08-21 21:22:15.000000000 +0200 +@@ -0,0 +1,60 @@ +/* -+ * Suspend support for mips. ++ * Suspend support specific for mips. + * -+ * Distributed under GPLv2 ++ * Licensed under the GPLv2 + * + * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology + * Author: Hu Hongbing @@ -18063,6 +18335,7 @@ diff -Nur linux-2.6.30.orig/arch/mips/power/cpu.c linux-2.6.30/arch/mips/power/c +#include +#include +#include ++#include + +static u32 saved_status; +struct pt_regs saved_regs; @@ -18087,21 +18360,37 @@ diff -Nur linux-2.6.30.orig/arch/mips/power/cpu.c linux-2.6.30/arch/mips/power/c + restore_dsp(current); +} + ++int pfn_in_system_ram(unsigned long pfn) ++{ ++ int i; ++ ++ for (i = 0; i < boot_mem_map.nr_map; i++) { ++ if (boot_mem_map.map[i].type == BOOT_MEM_RAM) { ++ if ((pfn >= (boot_mem_map.map[i].addr >> PAGE_SHIFT)) && ++ ((pfn) < ((boot_mem_map.map[i].addr + ++ boot_mem_map.map[i].size) >> PAGE_SHIFT))) ++ return 1; ++ } ++ } ++ return 0; ++} ++ +int pfn_is_nosave(unsigned long pfn) +{ + unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin)); + unsigned long nosave_end_pfn = PFN_UP(__pa(&__nosave_end)); + -+ return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); ++ return ((pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn)) ++ || !pfn_in_system_ram(pfn); +} -diff -Nur linux-2.6.30.orig/arch/mips/power/hibernate.S linux-2.6.30/arch/mips/power/hibernate.S ---- linux-2.6.30.orig/arch/mips/power/hibernate.S 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/power/hibernate.S 2009-06-14 20:25:19.000000000 +0200 -@@ -0,0 +1,70 @@ +diff -Nur linux-2.6.30.5.orig/arch/mips/power/hibernate.S linux-2.6.30.5/arch/mips/power/hibernate.S +--- linux-2.6.30.5.orig/arch/mips/power/hibernate.S 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/power/hibernate.S 2009-08-21 21:22:15.000000000 +0200 +@@ -0,0 +1,61 @@ +/* -+ * Hibernation support for mips - temporary page tables ++ * Hibernation support specific for mips - temporary page tables + * -+ * Distributed under GPLv2 ++ * Licensed under the GPLv2 + * + * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology + * Author: Hu Hongbing @@ -18143,15 +18432,6 @@ diff -Nur linux-2.6.30.orig/arch/mips/power/hibernate.S linux-2.6.30/arch/mips/p + bne t1, t3, 1b + PTR_L t0, PBE_NEXT(t0) + bnez t0, 0b -+ /* flush caches to make sure context is in memory */ -+ PTR_L t0, __flush_cache_all -+ jalr t0 -+ /* flush tlb entries */ -+#ifdef CONFIG_SMP -+ jal flush_tlb_all -+#else -+ jal local_flush_tlb_all -+#endif + PTR_LA t0, saved_regs + PTR_L ra, PT_R31(t0) + PTR_L sp, PT_R29(t0) @@ -18168,3221 +18448,35882 @@ diff -Nur linux-2.6.30.orig/arch/mips/power/hibernate.S linux-2.6.30/arch/mips/p + PTR_LI v0, 0x0 + jr ra +END(swsusp_arch_resume) -diff -Nur linux-2.6.30.orig/arch/mips/power/Makefile linux-2.6.30/arch/mips/power/Makefile ---- linux-2.6.30.orig/arch/mips/power/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/arch/mips/power/Makefile 2009-06-14 20:25:19.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/arch/mips/power/Makefile linux-2.6.30.5/arch/mips/power/Makefile +--- linux-2.6.30.5.orig/arch/mips/power/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/arch/mips/power/Makefile 2009-08-21 21:22:15.000000000 +0200 @@ -0,0 +1 @@ +obj-$(CONFIG_HIBERNATION) += cpu.o hibernate.o -diff -Nur linux-2.6.30.orig/arch/mips/sibyte/bcm1480/irq.c linux-2.6.30/arch/mips/sibyte/bcm1480/irq.c ---- linux-2.6.30.orig/arch/mips/sibyte/bcm1480/irq.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/sibyte/bcm1480/irq.c 2009-06-14 20:25:19.000000000 +0200 -@@ -116,10 +116,6 @@ - unsigned long flags; - unsigned int irq_dirty; - -- if (cpumask_weight(mask) != 1) { -- printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq); -- return; -- } - i = cpumask_first(mask); - - /* Convert logical CPU to physical CPU */ -diff -Nur linux-2.6.30.orig/arch/mips/sibyte/sb1250/irq.c linux-2.6.30/arch/mips/sibyte/sb1250/irq.c ---- linux-2.6.30.orig/arch/mips/sibyte/sb1250/irq.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/sibyte/sb1250/irq.c 2009-06-14 20:25:19.000000000 +0200 -@@ -111,11 +111,6 @@ - - i = cpumask_first(mask); - -- if (cpumask_weight(mask) > 1) { -- printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq); -- return; -- } -- - /* Convert logical CPU to physical CPU */ - cpu = cpu_logical_map(i); - -diff -Nur linux-2.6.30.orig/arch/mips/txx9/generic/pci.c linux-2.6.30/arch/mips/txx9/generic/pci.c ---- linux-2.6.30.orig/arch/mips/txx9/generic/pci.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/mips/txx9/generic/pci.c 2009-06-14 20:25:19.000000000 +0200 -@@ -382,7 +382,7 @@ - return 0; - } +diff -Nur linux-2.6.30.5.orig/drivers/input/serio/i8042.c linux-2.6.30.5/drivers/input/serio/i8042.c +--- linux-2.6.30.5.orig/drivers/input/serio/i8042.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/drivers/input/serio/i8042.c 2009-08-22 11:56:23.000000000 +0200 +@@ -143,7 +143,7 @@ + * of the i8042 down the toilet. + */ --int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +-static int i8042_flush(void) ++int i8042_flush(void) { - return txx9_board_vec->pci_map_irq(dev, slot, pin); - } -diff -Nur linux-2.6.30.orig/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c linux-2.6.30/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c ---- linux-2.6.30.orig/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c 2009-06-14 20:25:19.000000000 +0200 -@@ -550,7 +550,7 @@ - return -ENOMEM; - } - for_each_possible_cpu(i) { -- if (!zalloc_cpumask_var_node( -+ if (!alloc_cpumask_var_node( - &per_cpu_ptr(acpi_perf_data, i)->shared_cpu_map, - GFP_KERNEL, cpu_to_node(i))) { - -diff -Nur linux-2.6.30.orig/arch/x86/kernel/cpu/cpufreq/powernow-k7.c linux-2.6.30/arch/x86/kernel/cpu/cpufreq/powernow-k7.c ---- linux-2.6.30.orig/arch/x86/kernel/cpu/cpufreq/powernow-k7.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/x86/kernel/cpu/cpufreq/powernow-k7.c 2009-06-14 20:25:19.000000000 +0200 -@@ -322,7 +322,7 @@ - goto err0; - } - -- if (!zalloc_cpumask_var(&acpi_processor_perf->shared_cpu_map, -+ if (!alloc_cpumask_var(&acpi_processor_perf->shared_cpu_map, - GFP_KERNEL)) { - retval = -ENOMEM; - goto err05; -diff -Nur linux-2.6.30.orig/arch/x86/kernel/cpu/cpufreq/powernow-k8.c linux-2.6.30/arch/x86/kernel/cpu/cpufreq/powernow-k8.c ---- linux-2.6.30.orig/arch/x86/kernel/cpu/cpufreq/powernow-k8.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/x86/kernel/cpu/cpufreq/powernow-k8.c 2009-06-14 20:25:19.000000000 +0200 -@@ -887,7 +887,7 @@ - /* notify BIOS that we exist */ - acpi_processor_notify_smm(THIS_MODULE); - -- if (!zalloc_cpumask_var(&data->acpi_data.shared_cpu_map, GFP_KERNEL)) { -+ if (!alloc_cpumask_var(&data->acpi_data.shared_cpu_map, GFP_KERNEL)) { - printk(KERN_ERR PFX - "unable to alloc powernow_k8_data cpumask\n"); - ret_val = -ENOMEM; -diff -Nur linux-2.6.30.orig/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c linux-2.6.30/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c ---- linux-2.6.30.orig/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c 2009-06-14 20:25:19.000000000 +0200 -@@ -471,7 +471,7 @@ - - if (unlikely(!alloc_cpumask_var(&saved_mask, GFP_KERNEL))) - return -ENOMEM; -- if (unlikely(!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL))) { -+ if (unlikely(!alloc_cpumask_var(&covered_cpus, GFP_KERNEL))) { - free_cpumask_var(saved_mask); - return -ENOMEM; - } -diff -Nur linux-2.6.30.orig/arch/x86/kernel/cpu/mcheck/mce_64.c linux-2.6.30/arch/x86/kernel/cpu/mcheck/mce_64.c ---- linux-2.6.30.orig/arch/x86/kernel/cpu/mcheck/mce_64.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/x86/kernel/cpu/mcheck/mce_64.c 2009-06-14 20:25:19.000000000 +0200 -@@ -1163,7 +1163,7 @@ - if (!mce_available(&boot_cpu_data)) - return -EIO; - -- zalloc_cpumask_var(&mce_device_initialized, GFP_KERNEL); -+ alloc_cpumask_var(&mce_device_initialized, GFP_KERNEL); - - err = mce_init_banks(); - if (err) -diff -Nur linux-2.6.30.orig/arch/x86/kernel/tlb_uv.c linux-2.6.30/arch/x86/kernel/tlb_uv.c ---- linux-2.6.30.orig/arch/x86/kernel/tlb_uv.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/arch/x86/kernel/tlb_uv.c 2009-06-14 20:25:19.000000000 +0200 -@@ -832,7 +832,7 @@ - return 0; - - for_each_possible_cpu(cur_cpu) -- zalloc_cpumask_var_node(&per_cpu(uv_flush_tlb_mask, cur_cpu), -+ alloc_cpumask_var_node(&per_cpu(uv_flush_tlb_mask, cur_cpu), - GFP_KERNEL, cpu_to_node(cur_cpu)); - - uv_bau_retry_limit = 1; -diff -Nur linux-2.6.30.orig/block/bsg.c linux-2.6.30/block/bsg.c ---- linux-2.6.30.orig/block/bsg.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/block/bsg.c 2009-06-14 20:25:19.000000000 +0200 -@@ -315,7 +315,6 @@ - blk_put_request(rq); - if (next_rq) { - blk_rq_unmap_user(next_rq->bio); -- next_rq->bio = NULL; - blk_put_request(next_rq); - } - return ERR_PTR(ret); -@@ -449,7 +448,6 @@ - hdr->dout_resid = rq->data_len; - hdr->din_resid = rq->next_rq->data_len; - blk_rq_unmap_user(bidi_bio); -- rq->next_rq->bio = NULL; - blk_put_request(rq->next_rq); - } else if (rq_data_dir(rq) == READ) - hdr->din_resid = rq->data_len; -@@ -468,7 +466,6 @@ - blk_rq_unmap_user(bio); - if (rq->cmd != rq->__cmd) - kfree(rq->cmd); -- rq->bio = NULL; - blk_put_request(rq); - - return ret; -diff -Nur linux-2.6.30.orig/Documentation/kernel-parameters.txt linux-2.6.30/Documentation/kernel-parameters.txt ---- linux-2.6.30.orig/Documentation/kernel-parameters.txt 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/Documentation/kernel-parameters.txt 2009-06-14 20:25:19.000000000 +0200 -@@ -1220,6 +1220,10 @@ - (machvec) in a generic kernel. - Example: machvec=hpzx1_swiotlb - -+ machtype= [Loongson] Share the same kernel image file between different -+ yeeloong laptop. -+ Example: machtype=lemote-yeeloong-2f-7inch -+ - max_addr=nn[KMG] [KNL,BOOT,ia64] All physical memory greater - than or equal to this physical address is ignored. - -diff -Nur linux-2.6.30.orig/drivers/acpi/processor_core.c linux-2.6.30/drivers/acpi/processor_core.c ---- linux-2.6.30.orig/drivers/acpi/processor_core.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/drivers/acpi/processor_core.c 2009-06-14 20:25:19.000000000 +0200 -@@ -844,7 +844,7 @@ - if (!pr) - return -ENOMEM; - -- if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) { -+ if (!alloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) { - kfree(pr); - return -ENOMEM; - } -diff -Nur linux-2.6.30.orig/drivers/char/mxser.c linux-2.6.30/drivers/char/mxser.c ---- linux-2.6.30.orig/drivers/char/mxser.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/drivers/char/mxser.c 2009-06-14 20:25:19.000000000 +0200 -@@ -2711,7 +2711,7 @@ - continue; - - brd = &mxser_boards[m]; -- retval = mxser_get_ISA_conf(ioaddr[b], brd); -+ retval = mxser_get_ISA_conf(!ioaddr[b], brd); - if (retval <= 0) { - brd->info = NULL; - continue; -diff -Nur linux-2.6.30.orig/drivers/cpufreq/cpufreq.c linux-2.6.30/drivers/cpufreq/cpufreq.c ---- linux-2.6.30.orig/drivers/cpufreq/cpufreq.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/drivers/cpufreq/cpufreq.c 2009-06-14 20:25:19.000000000 +0200 -@@ -808,7 +808,7 @@ - ret = -ENOMEM; - goto nomem_out; - } -- if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) { -+ if (!alloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) { - free_cpumask_var(policy->cpus); - kfree(policy); - ret = -ENOMEM; -diff -Nur linux-2.6.30.orig/drivers/ide/amd74xx.c linux-2.6.30/drivers/ide/amd74xx.c ---- linux-2.6.30.orig/drivers/ide/amd74xx.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/drivers/ide/amd74xx.c 2009-06-14 20:25:19.000000000 +0200 -@@ -23,6 +23,11 @@ - - #define DRV_NAME "amd74xx" - -+static const char *am74xx_quirk_drives[] = { -+ "FUJITSU MHZ2160BH G2", -+ NULL -+}; -+ - enum { - AMD_IDE_CONFIG = 0x41, - AMD_CABLE_DETECT = 0x42, -@@ -112,6 +117,19 @@ - amd_set_drive(drive, XFER_PIO_0 + pio); + unsigned long flags; + unsigned char data, str; +@@ -390,10 +390,10 @@ } -+static void amd_quirkproc(ide_drive_t *drive) -+{ -+ const char **list, *m = (char *)&drive->id[ATA_ID_PROD]; -+ -+ for (list = am74xx_quirk_drives; *list != NULL; list++) -+ if (strstr(m, *list) != NULL) { -+ drive->quirk_list = 2; -+ return; -+ } -+ -+ drive->quirk_list = 0; -+} -+ - static void amd7409_cable_detect(struct pci_dev *dev) - { - /* no host side cable detection */ -@@ -186,6 +204,7 @@ - static const struct ide_port_ops amd_port_ops = { - .set_pio_mode = amd_set_pio_mode, - .set_dma_mode = amd_set_drive, -+ .quirkproc = amd_quirkproc, - .cable_detect = amd_cable_detect, - }; - -diff -Nur linux-2.6.30.orig/drivers/md/raid5.c linux-2.6.30/drivers/md/raid5.c ---- linux-2.6.30.orig/drivers/md/raid5.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/drivers/md/raid5.c 2009-06-14 20:25:20.000000000 +0200 -@@ -362,7 +362,7 @@ - - static struct stripe_head * - get_active_stripe(raid5_conf_t *conf, sector_t sector, -- int previous, int noblock, int noquiesce) -+ int previous, int noblock) - { - struct stripe_head *sh; - -@@ -372,7 +372,7 @@ - - do { - wait_event_lock_irq(conf->wait_for_stripe, -- conf->quiesce == 0 || noquiesce, -+ conf->quiesce == 0, - conf->device_lock, /* nothing */); - sh = __find_stripe(conf, sector, conf->generation - previous); - if (!sh) { -@@ -2671,7 +2671,7 @@ - sector_t bn = compute_blocknr(sh, i, 1); - sector_t s = raid5_compute_sector(conf, bn, 0, - &dd_idx, NULL); -- sh2 = get_active_stripe(conf, s, 0, 1, 1); -+ sh2 = get_active_stripe(conf, s, 0, 1); - if (sh2 == NULL) - /* so far only the early blocks of this stripe - * have been requested. When later blocks -@@ -2944,7 +2944,7 @@ - /* Finish reconstruct operations initiated by the expansion process */ - if (sh->reconstruct_state == reconstruct_state_result) { - struct stripe_head *sh2 -- = get_active_stripe(conf, sh->sector, 1, 1, 1); -+ = get_active_stripe(conf, sh->sector, 1, 1); - if (sh2 && test_bit(STRIPE_EXPAND_SOURCE, &sh2->state)) { - /* sh cannot be written until sh2 has been read. - * so arrange for sh to be delayed a little -@@ -3189,7 +3189,7 @@ - - if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state)) { - struct stripe_head *sh2 -- = get_active_stripe(conf, sh->sector, 1, 1, 1); -+ = get_active_stripe(conf, sh->sector, 1, 1); - if (sh2 && test_bit(STRIPE_EXPAND_SOURCE, &sh2->state)) { - /* sh cannot be written until sh2 has been read. - * so arrange for sh to be delayed a little -@@ -3288,7 +3288,7 @@ - int i; - - rcu_read_lock(); -- for (i = 0; i < conf->raid_disks; i++) { -+ for (i=0; iraid_disks; i++) { - mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { - struct request_queue *r_queue = bdev_get_queue(rdev->bdev); -@@ -3675,7 +3675,7 @@ - (unsigned long long)logical_sector); - - sh = get_active_stripe(conf, new_sector, previous, -- (bi->bi_rw&RWA_MASK), 0); -+ (bi->bi_rw&RWA_MASK)); - if (sh) { - if (unlikely(previous)) { - /* expansion might have moved on while waiting for a -@@ -3873,7 +3873,7 @@ - for (i = 0; i < reshape_sectors; i += STRIPE_SECTORS) { - int j; - int skipped = 0; -- sh = get_active_stripe(conf, stripe_addr+i, 0, 0, 1); -+ sh = get_active_stripe(conf, stripe_addr+i, 0, 0); - set_bit(STRIPE_EXPANDING, &sh->state); - atomic_inc(&conf->reshape_stripes); - /* If any of this stripe is beyond the end of the old -@@ -3916,13 +3916,13 @@ - raid5_compute_sector(conf, stripe_addr*(new_data_disks), - 1, &dd_idx, NULL); - last_sector = -- raid5_compute_sector(conf, ((stripe_addr+reshape_sectors) -+ raid5_compute_sector(conf, ((stripe_addr+conf->chunk_size/512) - *(new_data_disks) - 1), - 1, &dd_idx, NULL); - if (last_sector >= mddev->dev_sectors) - last_sector = mddev->dev_sectors - 1; - while (first_sector <= last_sector) { -- sh = get_active_stripe(conf, first_sector, 1, 0, 1); -+ sh = get_active_stripe(conf, first_sector, 1, 0); - set_bit(STRIPE_EXPAND_SOURCE, &sh->state); - set_bit(STRIPE_HANDLE, &sh->state); - release_stripe(sh); -@@ -4022,9 +4022,9 @@ - - bitmap_cond_end_sync(mddev->bitmap, sector_nr); - -- sh = get_active_stripe(conf, sector_nr, 0, 1, 0); -+ sh = get_active_stripe(conf, sector_nr, 0, 1); - if (sh == NULL) { -- sh = get_active_stripe(conf, sector_nr, 0, 0, 0); -+ sh = get_active_stripe(conf, sector_nr, 0, 0); - /* make sure we don't swamp the stripe cache if someone else - * is trying to get access - */ -@@ -4034,7 +4034,7 @@ - * We don't need to check the 'failed' flag as when that gets set, - * recovery aborts. - */ -- for (i = 0; i < conf->raid_disks; i++) -+ for (i=0; iraid_disks; i++) - if (conf->disks[i].rdev == NULL) - still_degraded = 1; - -@@ -4086,7 +4086,7 @@ - /* already done this stripe */ - continue; - -- sh = get_active_stripe(conf, sector, 0, 1, 0); -+ sh = get_active_stripe(conf, sector, 0, 1); - - if (!sh) { - /* failed to get a stripe - must wait */ -diff -Nur linux-2.6.30.orig/drivers/net/Kconfig linux-2.6.30/drivers/net/Kconfig ---- linux-2.6.30.orig/drivers/net/Kconfig 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/drivers/net/Kconfig 2009-06-14 20:25:20.000000000 +0200 -@@ -2362,6 +2362,13 @@ - Some boards that use the Discovery chipset are the Momenco - Ocelot C and Jaguar ATX and Pegasos II. - -+config TITAN_GE -+ bool "PMC-Sierra TITAN Gigabit Ethernet Support" -+ depends on PMC_YOSEMITE -+ help -+ This enables support for the the integrated ethernet of -+ PMC-Sierra's Titan SoC. -+ - config QLA3XXX - tristate "QLogic QLA3XXX Network Driver Support" - depends on PCI -diff -Nur linux-2.6.30.orig/drivers/net/Makefile linux-2.6.30/drivers/net/Makefile ---- linux-2.6.30.orig/drivers/net/Makefile 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/drivers/net/Makefile 2009-06-14 20:25:20.000000000 +0200 -@@ -137,6 +137,8 @@ - obj-$(CONFIG_QLA3XXX) += qla3xxx.o - obj-$(CONFIG_QLGE) += qlge/ - -+obj-$(CONFIG_TITAN_GE) += titan_mdio.o titan_ge.o -+ - obj-$(CONFIG_PPP) += ppp_generic.o - obj-$(CONFIG_PPP_ASYNC) += ppp_async.o - obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o -diff -Nur linux-2.6.30.orig/drivers/net/r8169.c linux-2.6.30/drivers/net/r8169.c ---- linux-2.6.30.orig/drivers/net/r8169.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/drivers/net/r8169.c 2009-06-14 20:25:20.000000000 +0200 -@@ -66,6 +66,7 @@ - #define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ - #define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ - #define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -+#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ - #define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ - #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -@@ -2356,10 +2357,10 @@ - return cmd; - } + /* +- * i8042_enable_kbd_port enables keybaord port on chip ++ * i8042_enable_kbd_port enables keyboard port on chip + */ --static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -+static void rtl_set_rx_max_size(void __iomem *ioaddr) +-static int i8042_enable_kbd_port(void) ++int i8042_enable_kbd_port(void) { - /* Low hurts. Let's disable the filtering. */ -- RTL_W16(RxMaxSize, rx_buf_sz); -+ RTL_W16(RxMaxSize, 16383); - } - - static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -@@ -2406,7 +2407,7 @@ + i8042_ctr &= ~I8042_CTR_KBDDIS; + i8042_ctr |= I8042_CTR_KBDINT; +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/Kconfig linux-2.6.30.5/drivers/net/wireless/Kconfig +--- linux-2.6.30.5.orig/drivers/net/wireless/Kconfig 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/drivers/net/wireless/Kconfig 2009-08-21 21:18:15.000000000 +0200 +@@ -416,7 +416,7 @@ - RTL_W8(EarlyTxThres, EarlyTxThld); + config RTL8187 + tristate "Realtek 8187 and 8187B USB support" +- depends on MAC80211 && USB && WLAN_80211 ++ depends on MAC80211 && USB && WLAN_80211 && !LEMOTE_YEELOONG2F + select EEPROM_93CX6 + ---help--- + This is a driver for RTL8187 and RTL8187B based cards. +@@ -434,6 +434,16 @@ -- rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); -+ rtl_set_rx_max_size(ioaddr); + Thanks to Realtek for their support! - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || -@@ -2667,7 +2668,7 @@ ++config RTL8187B ++ tristate "Realtek 8187B wifi support for yeeloong2f laptop" ++ depends on MAC80211 && USB && WLAN_80211 && LEMOTE_YEELOONG2F ++ select EEPROM_93CX6 ++ ---help--- ++ This is a driver for RTL8187B based cards, this driver is especially ++ for yeeloon2f laptop. ++ ++ Thanks to Realtek for their support! ++ + config ADM8211 + tristate "ADMtek ADM8211 support" + depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/Makefile linux-2.6.30.5/drivers/net/wireless/Makefile +--- linux-2.6.30.5.orig/drivers/net/wireless/Makefile 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/drivers/net/wireless/Makefile 2009-08-21 21:18:15.000000000 +0200 +@@ -34,6 +34,7 @@ + obj-$(CONFIG_ZD1211RW) += zd1211rw/ + obj-$(CONFIG_RTL8180) += rtl818x/ + obj-$(CONFIG_RTL8187) += rtl818x/ ++obj-$(CONFIG_RTL8187B) += rtl8187b/ - RTL_W8(EarlyTxThres, EarlyTxThld); - -- rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); -+ rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - -@@ -2845,7 +2846,7 @@ - - RTL_W8(EarlyTxThres, EarlyTxThld); - -- rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); -+ rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - -diff -Nur linux-2.6.30.orig/drivers/net/titan_ge.c linux-2.6.30/drivers/net/titan_ge.c ---- linux-2.6.30.orig/drivers/net/titan_ge.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/drivers/net/titan_ge.c 2009-06-14 20:25:20.000000000 +0200 -@@ -0,0 +1,2069 @@ -+/* -+ * drivers/net/titan_ge.c - Driver for Titan ethernet ports + # 16-bit wireless PCMCIA client drivers + obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/dot11d.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/dot11d.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/dot11d.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/dot11d.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,102 @@ ++#ifndef __INC_DOT11D_H ++#define __INC_DOT11D_H ++ ++#include "ieee80211/ieee80211.h" ++ ++//#define ENABLE_DOT11D ++ ++//#define DOT11D_MAX_CHNL_NUM 83 ++ ++typedef struct _CHNL_TXPOWER_TRIPLE { ++ u8 FirstChnl; ++ u8 NumChnls; ++ u8 MaxTxPowerInDbm; ++}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE; ++ ++typedef enum _DOT11D_STATE { ++ DOT11D_STATE_NONE = 0, ++ DOT11D_STATE_LEARNED, ++ DOT11D_STATE_DONE, ++}DOT11D_STATE; ++ ++typedef struct _RT_DOT11D_INFO { ++ //DECLARE_RT_OBJECT(RT_DOT11D_INFO); ++ ++ bool bEnabled; // dot11MultiDomainCapabilityEnabled ++ ++ u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element. ++ u8 CountryIeBuf[MAX_IE_LEN]; ++ u8 CountryIeSrcAddr[6]; // Source AP of the country IE. ++ u8 CountryIeWatchdog; ++ ++ u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) ++ //u8 ChnlListLen; // #Bytes valid in ChnlList[]. ++ //u8 ChnlList[DOT11D_MAX_CHNL_NUM]; ++ u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; ++ ++ DOT11D_STATE State; ++}RT_DOT11D_INFO, *PRT_DOT11D_INFO; ++#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 ) ++#define cpMacAddr(des,src) ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5]) ++#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo)) ++ ++#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled ++#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0) ++ ++#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) ++#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) ++ ++#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \ ++ (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \ ++ FALSE : \ ++ (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length))) ++ ++#define CIE_WATCHDOG_TH 1 ++#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog ++#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0 ++#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev) ++ ++#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE) ++ ++ ++void ++Dot11d_Init( ++ struct ieee80211_device *dev ++ ); ++ ++void ++Dot11d_Reset( ++ struct ieee80211_device *dev ++ ); ++ ++void ++Dot11d_UpdateCountryIe( ++ struct ieee80211_device *dev, ++ u8 * pTaddr, ++ u16 CoutryIeLen, ++ u8 * pCoutryIe ++ ); ++ ++u8 ++DOT11D_GetMaxTxPwrInDbm( ++ struct ieee80211_device *dev, ++ u8 Channel ++ ); ++ ++void ++DOT11D_ScanComplete( ++ struct ieee80211_device * dev ++ ); ++ ++int IsLegalChannel( ++ struct ieee80211_device * dev, ++ u8 channel ++); ++ ++int ToLegalChannel( ++ struct ieee80211_device * dev, ++ u8 channel ++); ++ ++void dump_chnl_map(u8 * channel_map); ++#endif // #ifndef __INC_DOT11D_H +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/arc4.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/arc4.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/arc4.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/arc4.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,103 @@ ++/* ++ * Cryptographic API + * -+ * Copyright (C) 2003 PMC-Sierra Inc. -+ * Author : Manish Lachwani (lachwani@pmc-sierra.com) ++ * ARC4 Cipher Algorithm + * -+ * 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. ++ * Jon Oberheide + * -+ * 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. ++ * 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. + * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ -+ -+/* -+ * The MAC unit of the Titan consists of the following: -+ * -+ * -> XDMA Engine to move data to from the memory to the MAC packet FIFO -+ * -> FIFO is where the incoming and outgoing data is placed -+ * -> TRTG is the unit that pulls the data from the FIFO for Tx and pushes -+ * the data into the FIFO for Rx -+ * -> TMAC is the outgoing MAC interface and RMAC is the incoming. -+ * -> AFX is the address filtering block -+ * -> GMII block to communicate with the PHY -+ * -+ * Rx will look like the following: -+ * GMII --> RMAC --> AFX --> TRTG --> Rx FIFO --> XDMA --> CPU memory -+ * -+ * Tx will look like the following: -+ * CPU memory --> XDMA --> Tx FIFO --> TRTG --> TMAC --> GMII -+ * -+ * The Titan driver has support for the following performance features: -+ * -> Rx side checksumming -+ * -> Jumbo Frames -+ * -> Interrupt Coalscing -+ * -> Rx NAPI -+ * -> SKB Recycling -+ * -> Transmit/Receive descriptors in SRAM -+ * -> Fast routing for IP forwarding -+ */ -+ -+#include +#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include +#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* For MII specifc registers, titan_mdio.h should be included */ -+#include ++#include "rtl_crypto.h" + -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "titan_ge.h" -+#include "titan_mdio.h" ++#define ARC4_MIN_KEY_SIZE 1 ++#define ARC4_MAX_KEY_SIZE 256 ++#define ARC4_BLOCK_SIZE 1 + -+/* Static Function Declarations */ -+static int titan_ge_eth_open(struct net_device *); -+static void titan_ge_eth_stop(struct net_device *); -+static struct net_device_stats *titan_ge_get_stats(struct net_device *); -+static int titan_ge_init_rx_desc_ring(titan_ge_port_info *, int, int, -+ unsigned long, unsigned long, -+ unsigned long); -+static int titan_ge_init_tx_desc_ring(titan_ge_port_info *, int, -+ unsigned long, unsigned long); -+ -+static int titan_ge_open(struct net_device *); -+static int titan_ge_start_xmit(struct sk_buff *, struct net_device *); -+static int titan_ge_stop(struct net_device *); ++struct arc4_ctx { ++ u8 S[256]; ++ u8 x, y; ++}; + -+static unsigned long titan_ge_tx_coal(unsigned long, int); ++static int arc4_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) ++{ ++ struct arc4_ctx *ctx = ctx_arg; ++ int i, j = 0, k = 0; + -+static void titan_ge_port_reset(unsigned int); -+static int titan_ge_free_tx_queue(titan_ge_port_info *); -+static int titan_ge_rx_task(struct net_device *, titan_ge_port_info *); -+static int titan_ge_port_start(struct net_device *, titan_ge_port_info *); ++ ctx->x = 1; ++ ctx->y = 0; + -+static int titan_ge_return_tx_desc(titan_ge_port_info *, int); ++ for(i = 0; i < 256; i++) ++ ctx->S[i] = i; + -+/* -+ * Some configuration for the FIFO and the XDMA channel needs -+ * to be done only once for all the ports. This flag controls -+ * that -+ */ -+static unsigned long config_done; ++ for(i = 0; i < 256; i++) ++ { ++ u8 a = ctx->S[i]; ++ j = (j + in_key[k] + a) & 0xff; ++ ctx->S[i] = ctx->S[j]; ++ ctx->S[j] = a; ++ if(++k >= key_len) ++ k = 0; ++ } + -+/* -+ * One time out of memory flag -+ */ -+static unsigned int oom_flag; ++ return 0; ++} + -+static int titan_ge_poll(struct net_device *netdev, int *budget); ++static void arc4_crypt(void *ctx_arg, u8 *out, const u8 *in) ++{ ++ struct arc4_ctx *ctx = ctx_arg; ++ ++ u8 *const S = ctx->S; ++ u8 x = ctx->x; ++ u8 y = ctx->y; ++ u8 a, b; ++ ++ a = S[x]; ++ y = (y + a) & 0xff; ++ b = S[y]; ++ S[x] = b; ++ S[y] = a; ++ x = (x + 1) & 0xff; ++ *out++ = *in ^ S[(a + b) & 0xff]; ++ ++ ctx->x = x; ++ ctx->y = y; ++} + -+static int titan_ge_receive_queue(struct net_device *, unsigned int); ++static struct crypto_alg arc4_alg = { ++ .cra_name = "arc4", ++ .cra_flags = CRYPTO_ALG_TYPE_CIPHER, ++ .cra_blocksize = ARC4_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct arc4_ctx), ++ .cra_module = THIS_MODULE, ++ .cra_list = LIST_HEAD_INIT(arc4_alg.cra_list), ++ .cra_u = { .cipher = { ++ .cia_min_keysize = ARC4_MIN_KEY_SIZE, ++ .cia_max_keysize = ARC4_MAX_KEY_SIZE, ++ .cia_setkey = arc4_set_key, ++ .cia_encrypt = arc4_crypt, ++ .cia_decrypt = arc4_crypt } } ++}; + -+static struct platform_device *titan_ge_device[3]; ++static int __init arc4_init(void) ++{ ++ return crypto_register_alg(&arc4_alg); ++} + -+/* MAC Address */ -+extern unsigned char titan_ge_mac_addr_base[6]; + -+unsigned long titan_ge_base; -+static unsigned long titan_ge_sram; ++static void __exit arc4_exit(void) ++{ ++ crypto_unregister_alg(&arc4_alg); ++} + -+static char titan_string[] = "titan"; ++module_init(arc4_init); ++module_exit(arc4_exit); + ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); ++MODULE_AUTHOR("Jon Oberheide "); +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/dot11d.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/dot11d.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/dot11d.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/dot11d.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,245 @@ ++#ifdef ENABLE_DOT11D ++//----------------------------------------------------------------------------- ++// File: ++// Dot11d.c ++// ++// Description: ++// Implement 802.11d. ++// ++//----------------------------------------------------------------------------- ++ ++#include "dot11d.h" ++ ++void ++Dot11d_Init(struct ieee80211_device *ieee) ++{ ++ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); ++ ++ pDot11dInfo->bEnabled = 0; ++ ++ pDot11dInfo->State = DOT11D_STATE_NONE; ++ pDot11dInfo->CountryIeLen = 0; ++ memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); ++ memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); ++ RESET_CIE_WATCHDOG(ieee); ++ ++ //printk("Dot11d_Init()\n"); ++} ++ ++// ++// Description: ++// Reset to the state as we are just entering a regulatory domain. ++// ++void ++Dot11d_Reset(struct ieee80211_device *ieee) ++{ ++ u32 i; ++ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); ++ ++ // Clear old channel map ++ memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); ++ memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); ++ // Set new channel map ++ for (i=1; i<=11; i++) { ++ (pDot11dInfo->channel_map)[i] = 1; ++ } ++ for (i=12; i<=14; i++) { ++ (pDot11dInfo->channel_map)[i] = 2; ++ } ++ ++ pDot11dInfo->State = DOT11D_STATE_NONE; ++ pDot11dInfo->CountryIeLen = 0; ++ RESET_CIE_WATCHDOG(ieee); ++ ++ //printk("Dot11d_Reset()\n"); ++} ++ ++// ++// Description: ++// Update country IE from Beacon or Probe Resopnse ++// and configure PHY for operation in the regulatory domain. ++// ++// TODO: ++// Configure Tx power. ++// ++// Assumption: ++// 1. IS_DOT11D_ENABLE() is TRUE. ++// 2. Input IE is an valid one. ++// ++void ++Dot11d_UpdateCountryIe( ++ struct ieee80211_device *dev, ++ u8 * pTaddr, ++ u16 CoutryIeLen, ++ u8 * pCoutryIe ++ ) ++{ ++ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); ++ u8 i, j, NumTriples, MaxChnlNum; ++ PCHNL_TXPOWER_TRIPLE pTriple; ++ ++ if((CoutryIeLen - 3)%3 != 0) ++ { ++ printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); ++ Dot11d_Reset(dev); ++ return; ++ } ++ ++ memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); ++ memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); ++ MaxChnlNum = 0; ++ NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string. ++ pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3); ++ for(i = 0; i < NumTriples; i++) ++ { ++ if(MaxChnlNum >= pTriple->FirstChnl) ++ { // It is not in a monotonically increasing order, so stop processing. ++ printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); ++ Dot11d_Reset(dev); ++ return; ++ } ++ if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls)) ++ { // It is not a valid set of channel id, so stop processing. ++ printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n"); ++ Dot11d_Reset(dev); ++ return; ++ } ++ ++ for(j = 0 ; j < pTriple->NumChnls; j++) ++ { ++ pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1; ++ pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm; ++ MaxChnlNum = pTriple->FirstChnl + j; ++ } ++ ++ pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3); ++ } ++#if 1 ++ //printk("Dot11d_UpdateCountryIe(): Channel List:\n"); ++ printk("Channel List:"); ++ for(i=1; i<= MAX_CHANNEL_NUMBER; i++) ++ if(pDot11dInfo->channel_map[i] > 0) ++ printk(" %d", i); ++ printk("\n"); ++#endif ++ ++ UPDATE_CIE_SRC(dev, pTaddr); ++ ++ pDot11dInfo->CountryIeLen = CoutryIeLen; ++ memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen); ++ pDot11dInfo->State = DOT11D_STATE_LEARNED; ++} ++ ++void dump_chnl_map(u8 * channel_map) ++{ ++ int i; ++ printk("Channel List:"); ++ for(i=1; i<= MAX_CHANNEL_NUMBER; i++) ++ if(channel_map[i] > 0) ++ printk(" %d(%d)", i, channel_map[i]); ++ printk("\n"); ++} ++ ++u8 ++DOT11D_GetMaxTxPwrInDbm( ++ struct ieee80211_device *dev, ++ u8 Channel ++ ) ++{ ++ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); ++ u8 MaxTxPwrInDbm = 255; ++ ++ if(MAX_CHANNEL_NUMBER < Channel) ++ { ++ printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n"); ++ return MaxTxPwrInDbm; ++ } ++ if(pDot11dInfo->channel_map[Channel]) ++ { ++ MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel]; ++ } ++ ++ return MaxTxPwrInDbm; ++} ++ ++ ++void ++DOT11D_ScanComplete( ++ struct ieee80211_device * dev ++ ) ++{ ++ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); ++ ++ switch(pDot11dInfo->State) ++ { ++ case DOT11D_STATE_LEARNED: ++ pDot11dInfo->State = DOT11D_STATE_DONE; ++ break; ++ ++ case DOT11D_STATE_DONE: ++ if( GET_CIE_WATCHDOG(dev) == 0 ) ++ { // Reset country IE if previous one is gone. ++ Dot11d_Reset(dev); ++ } ++ break; ++ case DOT11D_STATE_NONE: ++ break; ++ } ++} ++ ++int IsLegalChannel( ++ struct ieee80211_device * dev, ++ u8 channel ++) ++{ ++ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); ++ ++ if(MAX_CHANNEL_NUMBER < channel) ++ { ++ printk("IsLegalChannel(): Invalid Channel\n"); ++ return 0; ++ } ++ if(pDot11dInfo->channel_map[channel] > 0) ++ return 1; ++ return 0; ++} ++ ++int ToLegalChannel( ++ struct ieee80211_device * dev, ++ u8 channel ++) ++{ ++ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); ++ u8 default_chn = 0; ++ u32 i = 0; ++ ++ for (i=1; i<= MAX_CHANNEL_NUMBER; i++) ++ { ++ if(pDot11dInfo->channel_map[i] > 0) ++ { ++ default_chn = i; ++ break; ++ } ++ } ++ ++ if(MAX_CHANNEL_NUMBER < channel) ++ { ++ printk("IsLegalChannel(): Invalid Channel\n"); ++ return default_chn; ++ } ++ ++ if(pDot11dInfo->channel_map[channel] > 0) ++ return channel; ++ ++ return default_chn; ++} ++ ++EXPORT_SYMBOL(Dot11d_Init); ++EXPORT_SYMBOL(Dot11d_Reset); ++EXPORT_SYMBOL(Dot11d_UpdateCountryIe); ++EXPORT_SYMBOL(DOT11D_GetMaxTxPwrInDbm); ++EXPORT_SYMBOL(DOT11D_ScanComplete); ++EXPORT_SYMBOL(IsLegalChannel); ++EXPORT_SYMBOL(ToLegalChannel); ++#endif ++ +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/dot11d.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/dot11d.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/dot11d.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/dot11d.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,102 @@ ++#ifndef __INC_DOT11D_H ++#define __INC_DOT11D_H ++ ++#include "ieee80211.h" ++ ++//#define ENABLE_DOT11D ++ ++//#define DOT11D_MAX_CHNL_NUM 83 ++ ++typedef struct _CHNL_TXPOWER_TRIPLE { ++ u8 FirstChnl; ++ u8 NumChnls; ++ u8 MaxTxPowerInDbm; ++}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE; ++ ++typedef enum _DOT11D_STATE { ++ DOT11D_STATE_NONE = 0, ++ DOT11D_STATE_LEARNED, ++ DOT11D_STATE_DONE, ++}DOT11D_STATE; ++ ++typedef struct _RT_DOT11D_INFO { ++ //DECLARE_RT_OBJECT(RT_DOT11D_INFO); ++ ++ bool bEnabled; // dot11MultiDomainCapabilityEnabled ++ ++ u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element. ++ u8 CountryIeBuf[MAX_IE_LEN]; ++ u8 CountryIeSrcAddr[6]; // Source AP of the country IE. ++ u8 CountryIeWatchdog; ++ ++ u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) ++ //u8 ChnlListLen; // #Bytes valid in ChnlList[]. ++ //u8 ChnlList[DOT11D_MAX_CHNL_NUM]; ++ u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; ++ ++ DOT11D_STATE State; ++}RT_DOT11D_INFO, *PRT_DOT11D_INFO; ++#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 ) ++#define cpMacAddr(des,src) ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5]) ++#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo)) ++ ++#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled ++#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0) ++ ++#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) ++#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) ++ ++#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \ ++ (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \ ++ FALSE : \ ++ (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length))) ++ ++#define CIE_WATCHDOG_TH 1 ++#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog ++#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0 ++#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev) ++ ++#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE) ++ ++ ++void ++Dot11d_Init( ++ struct ieee80211_device *dev ++ ); ++ ++void ++Dot11d_Reset( ++ struct ieee80211_device *dev ++ ); ++ ++void ++Dot11d_UpdateCountryIe( ++ struct ieee80211_device *dev, ++ u8 * pTaddr, ++ u16 CoutryIeLen, ++ u8 * pCoutryIe ++ ); ++ ++u8 ++DOT11D_GetMaxTxPwrInDbm( ++ struct ieee80211_device *dev, ++ u8 Channel ++ ); ++ ++void ++DOT11D_ScanComplete( ++ struct ieee80211_device * dev ++ ); ++ ++int IsLegalChannel( ++ struct ieee80211_device * dev, ++ u8 channel ++); ++ ++int ToLegalChannel( ++ struct ieee80211_device * dev, ++ u8 channel ++); ++ ++void dump_chnl_map(u8 * channel_map); ++#endif // #ifndef __INC_DOT11D_H +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,275 @@ +/* -+ * The Titan GE has two alignment requirements: -+ * -> skb->data to be cacheline aligned (32 byte) -+ * -> IP header alignment to 16 bytes ++ * Host AP crypto routines + * -+ * The latter is not implemented. So, that results in an extra copy on -+ * the Rx. This is a big performance hog. For the former case, the -+ * dev_alloc_skb() has been replaced with titan_ge_alloc_skb(). The size -+ * requested is calculated: ++ * Copyright (c) 2002-2003, Jouni Malinen ++ * Portions Copyright (C) 2004, Intel Corporation + * -+ * Ethernet Frame Size : 1518 -+ * Ethernet Header : 14 -+ * Future Titan change for IP header alignment : 2 ++ * 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. See README and COPYING for ++ * more details. + * -+ * Hence, we allocate (1518 + 14 + 2+ 64) = 1580 bytes. For IP header -+ * alignment, we use skb_reserve(). + */ + -+#define ALIGNED_RX_SKB_ADDR(addr) \ -+ ((((unsigned long)(addr) + (64UL - 1UL)) \ -+ & ~(64UL - 1UL)) - (unsigned long)(addr)) -+ -+#define titan_ge_alloc_skb(__length, __gfp_flags) \ -+({ struct sk_buff *__skb; \ -+ __skb = alloc_skb((__length) + 64, (__gfp_flags)); \ -+ if(__skb) { \ -+ int __offset = (int) ALIGNED_RX_SKB_ADDR(__skb->data); \ -+ if(__offset) \ -+ skb_reserve(__skb, __offset); \ -+ } \ -+ __skb; \ -+}) ++//#include ++#include ++#include ++#include ++#include ++#include ++#include + -+/* -+ * Configure the GMII block of the Titan based on what the PHY tells us -+ */ -+static void titan_ge_gmii_config(int port_num) -+{ -+ unsigned int reg_data = 0, phy_reg; -+ int err; ++#include "ieee80211.h" + -+ err = titan_ge_mdio_read(port_num, TITAN_GE_MDIO_PHY_STATUS, &phy_reg); ++MODULE_AUTHOR("Jouni Malinen"); ++MODULE_DESCRIPTION("HostAP crypto"); ++MODULE_LICENSE("GPL"); + -+ if (err == TITAN_GE_MDIO_ERROR) { -+ printk(KERN_ERR -+ "Could not read PHY control register 0x11 \n"); -+ printk(KERN_ERR -+ "Setting speed to 1000 Mbps and Duplex to Full \n"); ++struct ieee80211_crypto_alg { ++ struct list_head list; ++ struct ieee80211_crypto_ops *ops; ++}; + -+ return; -+ } + -+ err = titan_ge_mdio_write(port_num, TITAN_GE_MDIO_PHY_IE, 0); ++struct ieee80211_crypto { ++ struct list_head algs; ++ spinlock_t lock; ++}; + -+ if (phy_reg & 0x8000) { -+ if (phy_reg & 0x2000) { -+ /* Full Duplex and 1000 Mbps */ -+ TITAN_GE_WRITE((TITAN_GE_GMII_CONFIG_MODE + -+ (port_num << 12)), 0x201); -+ } else { -+ /* Half Duplex and 1000 Mbps */ -+ TITAN_GE_WRITE((TITAN_GE_GMII_CONFIG_MODE + -+ (port_num << 12)), 0x2201); -+ } -+ } -+ if (phy_reg & 0x4000) { -+ if (phy_reg & 0x2000) { -+ /* Full Duplex and 100 Mbps */ -+ TITAN_GE_WRITE((TITAN_GE_GMII_CONFIG_MODE + -+ (port_num << 12)), 0x100); -+ } else { -+ /* Half Duplex and 100 Mbps */ -+ TITAN_GE_WRITE((TITAN_GE_GMII_CONFIG_MODE + -+ (port_num << 12)), 0x2100); -+ } -+ } -+ reg_data = TITAN_GE_READ(TITAN_GE_GMII_CONFIG_GENERAL + -+ (port_num << 12)); -+ reg_data |= 0x3; -+ TITAN_GE_WRITE((TITAN_GE_GMII_CONFIG_GENERAL + -+ (port_num << 12)), reg_data); -+} ++static struct ieee80211_crypto *hcrypt; + -+/* -+ * Enable the TMAC if it is not -+ */ -+static void titan_ge_enable_tx(unsigned int port_num) ++void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, ++ int force) +{ -+ unsigned long reg_data; ++ struct list_head *ptr, *n; ++ struct ieee80211_crypt_data *entry; + -+ reg_data = TITAN_GE_READ(TITAN_GE_TMAC_CONFIG_1 + (port_num << 12)); -+ if (!(reg_data & 0x8000)) { -+ printk("TMAC disabled for port %d!! \n", port_num); ++ for (ptr = ieee->crypt_deinit_list.next, n = ptr->next; ++ ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) { ++ entry = list_entry(ptr, struct ieee80211_crypt_data, list); + -+ reg_data |= 0x0001; /* Enable TMAC */ -+ reg_data |= 0x4000; /* CRC Check Enable */ -+ reg_data |= 0x2000; /* Padding enable */ -+ reg_data |= 0x0800; /* CRC Add enable */ -+ reg_data |= 0x0080; /* PAUSE frame */ ++ if (atomic_read(&entry->refcnt) != 0 && !force) ++ continue; ++ ++ list_del(ptr); + -+ TITAN_GE_WRITE((TITAN_GE_TMAC_CONFIG_1 + -+ (port_num << 12)), reg_data); ++ if (entry->ops) { ++ entry->ops->deinit(entry->priv); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ++ module_put(entry->ops->owner); ++#else ++ __MOD_DEC_USE_COUNT(entry->ops->owner); ++#endif ++ } ++ kfree(entry); + } +} + -+/* -+ * Tx Timeout function -+ */ -+static void titan_ge_tx_timeout(struct net_device *netdev) ++void ieee80211_crypt_deinit_handler(unsigned long data) +{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); ++ struct ieee80211_device *ieee = (struct ieee80211_device *)data; ++ unsigned long flags; + -+ printk(KERN_INFO "%s: TX timeout ", netdev->name); -+ printk(KERN_INFO "Resetting card \n"); ++ spin_lock_irqsave(&ieee->lock, flags); ++ ieee80211_crypt_deinit_entries(ieee, 0); ++ if (!list_empty(&ieee->crypt_deinit_list)) { ++ printk(KERN_DEBUG "%s: entries remaining in delayed crypt " ++ "deletion list\n", ieee->dev->name); ++ ieee->crypt_deinit_timer.expires = jiffies + HZ; ++ add_timer(&ieee->crypt_deinit_timer); ++ } ++ spin_unlock_irqrestore(&ieee->lock, flags); + -+ /* Do the reset outside of interrupt context */ -+ schedule_work(&titan_ge_eth->tx_timeout_task); +} + -+/* -+ * Update the AFX tables for UC and MC for slice 0 only -+ */ -+static void titan_ge_update_afx(titan_ge_port_info * titan_ge_eth) ++void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, ++ struct ieee80211_crypt_data **crypt) +{ -+ int port = titan_ge_eth->port_num; -+ unsigned int i; -+ volatile unsigned long reg_data = 0; -+ u8 p_addr[6]; -+ -+ memcpy(p_addr, titan_ge_eth->port_mac_addr, 6); -+ -+ /* Set the MAC address here for TMAC and RMAC */ -+ TITAN_GE_WRITE((TITAN_GE_TMAC_STATION_HI + (port << 12)), -+ ((p_addr[5] << 8) | p_addr[4])); -+ TITAN_GE_WRITE((TITAN_GE_TMAC_STATION_MID + (port << 12)), -+ ((p_addr[3] << 8) | p_addr[2])); -+ TITAN_GE_WRITE((TITAN_GE_TMAC_STATION_LOW + (port << 12)), -+ ((p_addr[1] << 8) | p_addr[0])); -+ -+ TITAN_GE_WRITE((TITAN_GE_RMAC_STATION_HI + (port << 12)), -+ ((p_addr[5] << 8) | p_addr[4])); -+ TITAN_GE_WRITE((TITAN_GE_RMAC_STATION_MID + (port << 12)), -+ ((p_addr[3] << 8) | p_addr[2])); -+ TITAN_GE_WRITE((TITAN_GE_RMAC_STATION_LOW + (port << 12)), -+ ((p_addr[1] << 8) | p_addr[0])); -+ -+ TITAN_GE_WRITE((0x112c | (port << 12)), 0x1); -+ /* Configure the eight address filters */ -+ for (i = 0; i < 8; i++) { -+ /* Select each of the eight filters */ -+ TITAN_GE_WRITE((TITAN_GE_AFX_ADDRS_FILTER_CTRL_2 + -+ (port << 12)), i); -+ -+ /* Configure the match */ -+ reg_data = 0x9; /* Forward Enable Bit */ -+ TITAN_GE_WRITE((TITAN_GE_AFX_ADDRS_FILTER_CTRL_0 + -+ (port << 12)), reg_data); -+ -+ /* Finally, AFX Exact Match Address Registers */ -+ TITAN_GE_WRITE((TITAN_GE_AFX_EXACT_MATCH_LOW + (port << 12)), -+ ((p_addr[1] << 8) | p_addr[0])); -+ TITAN_GE_WRITE((TITAN_GE_AFX_EXACT_MATCH_MID + (port << 12)), -+ ((p_addr[3] << 8) | p_addr[2])); -+ TITAN_GE_WRITE((TITAN_GE_AFX_EXACT_MATCH_HIGH + (port << 12)), -+ ((p_addr[5] << 8) | p_addr[4])); -+ -+ /* VLAN id set to 0 */ -+ TITAN_GE_WRITE((TITAN_GE_AFX_EXACT_MATCH_VID + -+ (port << 12)), 0); ++ struct ieee80211_crypt_data *tmp; ++ unsigned long flags; ++ ++ if (*crypt == NULL) ++ return; ++ ++ tmp = *crypt; ++ *crypt = NULL; ++ ++ /* must not run ops->deinit() while there may be pending encrypt or ++ * decrypt operations. Use a list of delayed deinits to avoid needing ++ * locking. */ ++ ++ spin_lock_irqsave(&ieee->lock, flags); ++ list_add(&tmp->list, &ieee->crypt_deinit_list); ++ if (!timer_pending(&ieee->crypt_deinit_timer)) { ++ ieee->crypt_deinit_timer.expires = jiffies + HZ; ++ add_timer(&ieee->crypt_deinit_timer); + } ++ spin_unlock_irqrestore(&ieee->lock, flags); +} + -+/* -+ * Actual Routine to reset the adapter when the timeout occurred -+ */ -+static void titan_ge_tx_timeout_task(struct net_device *netdev) ++int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) +{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); -+ int port = titan_ge_eth->port_num; ++ unsigned long flags; ++ struct ieee80211_crypto_alg *alg; ++ ++ if (hcrypt == NULL) ++ return -1; ++ ++ alg = kmalloc(sizeof(*alg), GFP_KERNEL); ++ if (alg == NULL) ++ return -ENOMEM; + -+ printk("Titan GE: Transmit timed out. Resetting ... \n"); ++ memset(alg, 0, sizeof(*alg)); ++ alg->ops = ops; + -+ /* Dump debug info */ -+ printk(KERN_ERR "TRTG cause : %x \n", -+ TITAN_GE_READ(0x100c + (port << 12))); ++ spin_lock_irqsave(&hcrypt->lock, flags); ++ list_add(&alg->list, &hcrypt->algs); ++ spin_unlock_irqrestore(&hcrypt->lock, flags); + -+ /* Fix this for the other ports */ -+ printk(KERN_ERR "FIFO cause : %x \n", TITAN_GE_READ(0x482c)); -+ printk(KERN_ERR "IE cause : %x \n", TITAN_GE_READ(0x0040)); -+ printk(KERN_ERR "XDMA GDI ERROR : %x \n", -+ TITAN_GE_READ(0x5008 + (port << 8))); -+ printk(KERN_ERR "CHANNEL ERROR: %x \n", -+ TITAN_GE_READ(TITAN_GE_CHANNEL0_INTERRUPT -+ + (port << 8))); ++ printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n", ++ ops->name); + -+ netif_device_detach(netdev); -+ titan_ge_port_reset(titan_ge_eth->port_num); -+ titan_ge_port_start(netdev, titan_ge_eth); -+ netif_device_attach(netdev); ++ return 0; +} + -+/* -+ * Change the MTU of the Ethernet Device -+ */ -+static int titan_ge_change_mtu(struct net_device *netdev, int new_mtu) ++int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops) +{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); + unsigned long flags; ++ struct list_head *ptr; ++ struct ieee80211_crypto_alg *del_alg = NULL; + -+ if ((new_mtu > 9500) || (new_mtu < 64)) -+ return -EINVAL; ++ if (hcrypt == NULL) ++ return -1; ++ ++ spin_lock_irqsave(&hcrypt->lock, flags); ++ for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { ++ struct ieee80211_crypto_alg *alg = ++ (struct ieee80211_crypto_alg *) ptr; ++ if (alg->ops == ops) { ++ list_del(&alg->list); ++ del_alg = alg; ++ break; ++ } ++ } ++ spin_unlock_irqrestore(&hcrypt->lock, flags); + -+ spin_lock_irqsave(&titan_ge_eth->lock, flags); ++ if (del_alg) { ++ printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " ++ "'%s'\n", ops->name); ++ kfree(del_alg); ++ } + -+ netdev->mtu = new_mtu; ++ return del_alg ? 0 : -1; ++} + -+ /* Now we have to reopen the interface so that SKBs with the new -+ * size will be allocated */ + -+ if (netif_running(netdev)) { -+ titan_ge_eth_stop(netdev); ++struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name) ++{ ++ unsigned long flags; ++ struct list_head *ptr; ++ struct ieee80211_crypto_alg *found_alg = NULL; + -+ if (titan_ge_eth_open(netdev) != TITAN_OK) { -+ printk(KERN_ERR -+ "%s: Fatal error on opening device\n", -+ netdev->name); -+ spin_unlock_irqrestore(&titan_ge_eth->lock, flags); -+ return -1; ++ if (hcrypt == NULL) ++ return NULL; ++ ++ spin_lock_irqsave(&hcrypt->lock, flags); ++ for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { ++ struct ieee80211_crypto_alg *alg = ++ (struct ieee80211_crypto_alg *) ptr; ++ if (strcmp(alg->ops->name, name) == 0) { ++ found_alg = alg; ++ break; + } + } ++ spin_unlock_irqrestore(&hcrypt->lock, flags); + -+ spin_unlock_irqrestore(&titan_ge_eth->lock, flags); -+ return 0; ++ if (found_alg) ++ return found_alg->ops; ++ else ++ return NULL; +} + -+/* -+ * Titan Gbe Interrupt Handler. All the three ports send interrupt to one line -+ * only. Once an interrupt is triggered, figure out the port and then check -+ * the channel. -+ */ -+static irqreturn_t titan_ge_int_handler(int irq, void *dev_id) -+{ -+ struct net_device *netdev = (struct net_device *) dev_id; -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); -+ unsigned int port_num = titan_ge_eth->port_num; -+ unsigned int reg_data; -+ unsigned int eth_int_cause_error = 0, is; -+ unsigned long eth_int_cause1; -+ int err = 0; -+#ifdef CONFIG_SMP -+ unsigned long eth_int_cause2; -+#endif + -+ /* Ack the CPU interrupt */ -+ switch (port_num) { -+ case 0: -+ is = OCD_READ(RM9000x2_OCD_INTP0STATUS1); -+ OCD_WRITE(RM9000x2_OCD_INTP0CLEAR1, is); ++static void * ieee80211_crypt_null_init(int keyidx) { return (void *) 1; } ++static void ieee80211_crypt_null_deinit(void *priv) {} ++ ++static struct ieee80211_crypto_ops ieee80211_crypt_null = { ++ .name = "NULL", ++ .init = ieee80211_crypt_null_init, ++ .deinit = ieee80211_crypt_null_deinit, ++ .encrypt_mpdu = NULL, ++ .decrypt_mpdu = NULL, ++ .encrypt_msdu = NULL, ++ .decrypt_msdu = NULL, ++ .set_key = NULL, ++ .get_key = NULL, ++ .extra_prefix_len = 0, ++ .extra_postfix_len = 0, ++ .owner = THIS_MODULE, ++}; + -+#ifdef CONFIG_SMP -+ is = OCD_READ(RM9000x2_OCD_INTP1STATUS1); -+ OCD_WRITE(RM9000x2_OCD_INTP1CLEAR1, is); -+#endif -+ break; + -+ case 1: -+ is = OCD_READ(RM9000x2_OCD_INTP0STATUS0); -+ OCD_WRITE(RM9000x2_OCD_INTP0CLEAR0, is); ++int __init ieee80211_crypto_init(void) ++{ ++ int ret = -ENOMEM; + -+#ifdef CONFIG_SMP -+ is = OCD_READ(RM9000x2_OCD_INTP1STATUS0); -+ OCD_WRITE(RM9000x2_OCD_INTP1CLEAR0, is); -+#endif -+ break; ++ hcrypt = kmalloc(sizeof(*hcrypt), GFP_KERNEL); ++ if (!hcrypt) ++ goto out; + -+ case 2: -+ is = OCD_READ(RM9000x2_OCD_INTP0STATUS4); -+ OCD_WRITE(RM9000x2_OCD_INTP0CLEAR4, is); ++ memset(hcrypt, 0, sizeof(*hcrypt)); ++ INIT_LIST_HEAD(&hcrypt->algs); ++ spin_lock_init(&hcrypt->lock); + -+#ifdef CONFIG_SMP -+ is = OCD_READ(RM9000x2_OCD_INTP1STATUS4); -+ OCD_WRITE(RM9000x2_OCD_INTP1CLEAR4, is); -+#endif ++ ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null); ++ if (ret < 0) { ++ kfree(hcrypt); ++ hcrypt = NULL; + } ++out: ++ return ret; ++} + -+ eth_int_cause1 = TITAN_GE_READ(TITAN_GE_INTR_XDMA_CORE_A); -+#ifdef CONFIG_SMP -+ eth_int_cause2 = TITAN_GE_READ(TITAN_GE_INTR_XDMA_CORE_B); -+#endif + -+ /* Spurious interrupt */ -+#ifdef CONFIG_SMP -+ if ( (eth_int_cause1 == 0) && (eth_int_cause2 == 0)) { -+#else -+ if (eth_int_cause1 == 0) { -+#endif -+ eth_int_cause_error = TITAN_GE_READ(TITAN_GE_CHANNEL0_INTERRUPT + -+ (port_num << 8)); ++void __exit ieee80211_crypto_deinit(void) ++{ ++ struct list_head *ptr, *n; ++ ++ if (hcrypt == NULL) ++ return; + -+ if (eth_int_cause_error == 0) -+ return IRQ_NONE; ++ for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs; ++ ptr = n, n = ptr->next) { ++ struct ieee80211_crypto_alg *alg = ++ (struct ieee80211_crypto_alg *) ptr; ++ list_del(ptr); ++ printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " ++ "'%s' (deinit)\n", alg->ops->name); ++ kfree(alg); + } + -+ /* Handle Tx first. No need to ack interrupts */ -+#ifdef CONFIG_SMP -+ if ( (eth_int_cause1 & 0x20202) || -+ (eth_int_cause2 & 0x20202) ) ++ kfree(hcrypt); ++} ++ ++#if 0 ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++EXPORT_SYMBOL(ieee80211_crypt_deinit_entries); ++EXPORT_SYMBOL(ieee80211_crypt_deinit_handler); ++EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit); ++ ++EXPORT_SYMBOL(ieee80211_register_crypto_ops); ++EXPORT_SYMBOL(ieee80211_unregister_crypto_ops); ++EXPORT_SYMBOL(ieee80211_get_crypto_ops); +#else -+ if (eth_int_cause1 & 0x20202) ++EXPORT_SYMBOL_NOVERS(ieee80211_crypt_deinit_entries); ++EXPORT_SYMBOL_NOVERS(ieee80211_crypt_deinit_handler); ++EXPORT_SYMBOL_NOVERS(ieee80211_crypt_delayed_deinit); ++ ++EXPORT_SYMBOL_NOVERS(ieee80211_register_crypto_ops); ++EXPORT_SYMBOL_NOVERS(ieee80211_unregister_crypto_ops); ++EXPORT_SYMBOL_NOVERS(ieee80211_get_crypto_ops); +#endif -+ titan_ge_free_tx_queue(titan_ge_eth); + -+ /* Handle the Rx next */ -+#ifdef CONFIG_SMP -+ if ( (eth_int_cause1 & 0x10101) || -+ (eth_int_cause2 & 0x10101)) { -+#else -+ if (eth_int_cause1 & 0x10101) { ++module_init(ieee80211_crypto_init); ++module_exit(ieee80211_crypto_deinit); +#endif -+ if (netif_rx_schedule_prep(netdev)) { -+ unsigned int ack; +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt_ccmp.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt_ccmp.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt_ccmp.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt_ccmp.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,524 @@ ++/* ++ * Host AP crypt: host-based CCMP encryption implementation for Host AP driver ++ * ++ * Copyright (c) 2003-2004, Jouni Malinen ++ * ++ * 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. See README and COPYING for ++ * more details. ++ */ + -+ ack = TITAN_GE_READ(TITAN_GE_INTR_XDMA_IE); -+ /* Disable Tx and Rx both */ -+ if (port_num == 0) -+ ack &= ~(0x3); -+ if (port_num == 1) -+ ack &= ~(0x300); ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+ if (port_num == 2) -+ ack &= ~(0x30000); ++#include "ieee80211.h" + -+ /* Interrupts have been disabled */ -+ TITAN_GE_WRITE(TITAN_GE_INTR_XDMA_IE, ack); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) ++#include "rtl_crypto.h" ++#else ++#include ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ #include ++#else ++ #include ++#endif + -+ __netif_rx_schedule(netdev); -+ } -+ } ++//#include + -+ /* Handle error interrupts */ -+ if (eth_int_cause_error && (eth_int_cause_error != 0x2)) { -+ printk(KERN_ERR -+ "XDMA Channel Error : %x on port %d\n", -+ eth_int_cause_error, port_num); ++MODULE_AUTHOR("Jouni Malinen"); ++MODULE_DESCRIPTION("Host AP crypt: CCMP"); ++MODULE_LICENSE("GPL"); + -+ printk(KERN_ERR -+ "XDMA GDI Hardware error : %x on port %d\n", -+ TITAN_GE_READ(0x5008 + (port_num << 8)), port_num); ++#define AES_BLOCK_LEN 16 ++#define CCMP_HDR_LEN 8 ++#define CCMP_MIC_LEN 8 ++#define CCMP_TK_LEN 16 ++#define CCMP_PN_LEN 6 + -+ printk(KERN_ERR -+ "XDMA currently has %d Rx descriptors \n", -+ TITAN_GE_READ(0x5048 + (port_num << 8))); ++struct ieee80211_ccmp_data { ++ u8 key[CCMP_TK_LEN]; ++ int key_set; + -+ printk(KERN_ERR -+ "XDMA currently has prefetcted %d Rx descriptors \n", -+ TITAN_GE_READ(0x505c + (port_num << 8))); ++ u8 tx_pn[CCMP_PN_LEN]; ++ u8 rx_pn[CCMP_PN_LEN]; + -+ TITAN_GE_WRITE((TITAN_GE_CHANNEL0_INTERRUPT + -+ (port_num << 8)), eth_int_cause_error); -+ } ++ u32 dot11RSNAStatsCCMPFormatErrors; ++ u32 dot11RSNAStatsCCMPReplays; ++ u32 dot11RSNAStatsCCMPDecryptErrors; + -+ /* -+ * PHY interrupt to inform abt the changes. Reading the -+ * PHY Status register will clear the interrupt -+ */ -+ if ((!(eth_int_cause1 & 0x30303)) && -+ (eth_int_cause_error == 0)) { -+ err = -+ titan_ge_mdio_read(port_num, -+ TITAN_GE_MDIO_PHY_IS, ®_data); -+ -+ if (reg_data & 0x0400) { -+ /* Link status change */ -+ titan_ge_mdio_read(port_num, -+ TITAN_GE_MDIO_PHY_STATUS, ®_data); -+ if (!(reg_data & 0x0400)) { -+ /* Link is down */ -+ netif_carrier_off(netdev); -+ netif_stop_queue(netdev); -+ } else { -+ /* Link is up */ -+ netif_carrier_on(netdev); -+ netif_wake_queue(netdev); ++ int key_idx; + -+ /* Enable the queue */ -+ titan_ge_enable_tx(port_num); -+ } -+ } -+ } ++ struct crypto_tfm *tfm; + -+ return IRQ_HANDLED; -+} ++ /* scratch buffers for virt_to_page() (crypto API) */ ++ u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], ++ tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN]; ++ u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; ++}; + -+/* -+ * Multicast and Promiscuous mode set. The -+ * set_multi entry point is called whenever the -+ * multicast address list or the network interface -+ * flags are updated. -+ */ -+static void titan_ge_set_multi(struct net_device *netdev) ++void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm, ++ const u8 pt[16], u8 ct[16]) +{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); -+ unsigned int port_num = titan_ge_eth->port_num; -+ unsigned long reg_data; ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ struct scatterlist src, dst; + -+ reg_data = TITAN_GE_READ(TITAN_GE_AFX_ADDRS_FILTER_CTRL_1 + -+ (port_num << 12)); ++ src.page = virt_to_page(pt); ++ src.offset = offset_in_page(pt); ++ src.length = AES_BLOCK_LEN; + -+ if (netdev->flags & IFF_PROMISC) { -+ reg_data |= 0x2; -+ } -+ else if (netdev->flags & IFF_ALLMULTI) { -+ reg_data |= 0x01; -+ reg_data |= 0x400; /* Use the 64-bit Multicast Hash bin */ -+ } -+ else { -+ reg_data = 0x2; -+ } ++ dst.page = virt_to_page(ct); ++ dst.offset = offset_in_page(ct); ++ dst.length = AES_BLOCK_LEN; + -+ TITAN_GE_WRITE((TITAN_GE_AFX_ADDRS_FILTER_CTRL_1 + -+ (port_num << 12)), reg_data); -+ if (reg_data & 0x01) { -+ TITAN_GE_WRITE((TITAN_GE_AFX_MULTICAST_HASH_LOW + -+ (port_num << 12)), 0xffff); -+ TITAN_GE_WRITE((TITAN_GE_AFX_MULTICAST_HASH_MIDLOW + -+ (port_num << 12)), 0xffff); -+ TITAN_GE_WRITE((TITAN_GE_AFX_MULTICAST_HASH_MIDHI + -+ (port_num << 12)), 0xffff); -+ TITAN_GE_WRITE((TITAN_GE_AFX_MULTICAST_HASH_HI + -+ (port_num << 12)), 0xffff); -+ } ++ crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN); ++ #else ++ crypto_cipher_encrypt_one((void*)tfm, ct, pt); ++ #endif +} + -+/* -+ * Open the network device -+ */ -+static int titan_ge_open(struct net_device *netdev) ++static void * ieee80211_ccmp_init(int key_idx) +{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); -+ unsigned int port_num = titan_ge_eth->port_num; -+ unsigned int irq = TITAN_ETH_PORT_IRQ - port_num; -+ int retval; -+ -+ retval = request_irq(irq, titan_ge_int_handler, -+ SA_INTERRUPT | SA_SAMPLE_RANDOM , netdev->name, netdev); -+ -+ if (retval != 0) { -+ printk(KERN_ERR "Cannot assign IRQ number to TITAN GE \n"); -+ return -1; ++ struct ieee80211_ccmp_data *priv; ++ ++ priv = kmalloc(sizeof(*priv), GFP_ATOMIC); ++ if (priv == NULL) ++ goto fail; ++ memset(priv, 0, sizeof(*priv)); ++ priv->key_idx = key_idx; ++ ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ priv->tfm = crypto_alloc_tfm("aes", 0); ++ if (priv->tfm == NULL) { ++ printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate " ++ "crypto API aes\n"); ++ goto fail; ++ } ++ #else ++ priv->tfm = (void*)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(priv->tfm)) { ++ printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate " ++ "crypto API aes\n"); ++ priv->tfm = NULL; ++ goto fail; ++ } ++ #endif ++ return priv; ++ ++fail: ++ if (priv) { ++ if (priv->tfm) ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ crypto_free_tfm(priv->tfm); ++ #else ++ crypto_free_cipher((void*)priv->tfm); ++ #endif ++ kfree(priv); + } + -+ netdev->irq = irq; -+ printk(KERN_INFO "Assigned IRQ %d to port %d\n", irq, port_num); ++ return NULL; ++} + -+ spin_lock_irq(&(titan_ge_eth->lock)); + -+ if (titan_ge_eth_open(netdev) != TITAN_OK) { -+ spin_unlock_irq(&(titan_ge_eth->lock)); -+ printk("%s: Error opening interface \n", netdev->name); -+ free_irq(netdev->irq, netdev); -+ return -EBUSY; -+ } ++static void ieee80211_ccmp_deinit(void *priv) ++{ ++ struct ieee80211_ccmp_data *_priv = priv; ++ if (_priv && _priv->tfm) ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ crypto_free_tfm(_priv->tfm); ++ #else ++ crypto_free_cipher((void*)_priv->tfm); ++ #endif ++ kfree(priv); ++} + -+ spin_unlock_irq(&(titan_ge_eth->lock)); + -+ return 0; ++static inline void xor_block(u8 *b, u8 *a, size_t len) ++{ ++ int i; ++ for (i = 0; i < len; i++) ++ b[i] ^= a[i]; +} + -+/* -+ * Allocate the SKBs for the Rx ring. Also used -+ * for refilling the queue -+ */ -+static int titan_ge_rx_task(struct net_device *netdev, -+ titan_ge_port_info *titan_ge_port) ++#ifndef JOHN_CCMP ++static void ccmp_init_blocks(struct crypto_tfm *tfm, ++ struct ieee80211_hdr *hdr, ++ u8 *pn, size_t dlen, u8 *b0, u8 *auth, ++ u8 *s0) +{ -+ struct device *device = &titan_ge_device[titan_ge_port->port_num]->dev; -+ volatile titan_ge_rx_desc *rx_desc; -+ struct sk_buff *skb; -+ int rx_used_desc; -+ int count = 0; -+ -+ while (titan_ge_port->rx_ring_skbs < titan_ge_port->rx_ring_size) { ++ u8 *pos, qc = 0; ++ size_t aad_len; ++ u16 fc; ++ int a4_included, qc_included; ++ u8 aad[2 * AES_BLOCK_LEN]; ++ ++ fc = le16_to_cpu(hdr->frame_ctl); ++ a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == ++ (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)); ++ /* ++ qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) && ++ (WLAN_FC_GET_STYPE(fc) & 0x08)); ++ */ ++ // fixed by David :2006.9.6 ++ qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) && ++ (WLAN_FC_GET_STYPE(fc) & 0x80)); ++ aad_len = 22; ++ if (a4_included) ++ aad_len += 6; ++ if (qc_included) { ++ pos = (u8 *) &hdr->addr4; ++ if (a4_included) ++ pos += 6; ++ qc = *pos & 0x0f; ++ aad_len += 2; ++ } ++ /* CCM Initial Block: ++ * Flag (Include authentication header, M=3 (8-octet MIC), ++ * L=1 (2-octet Dlen)) ++ * Nonce: 0x00 | A2 | PN ++ * Dlen */ ++ b0[0] = 0x59; ++ b0[1] = qc; ++ memcpy(b0 + 2, hdr->addr2, ETH_ALEN); ++ memcpy(b0 + 8, pn, CCMP_PN_LEN); ++ b0[14] = (dlen >> 8) & 0xff; ++ b0[15] = dlen & 0xff; ++ ++ /* AAD: ++ * FC with bits 4..6 and 11..13 masked to zero; 14 is always one ++ * A1 | A2 | A3 ++ * SC with bits 4..15 (seq#) masked to zero ++ * A4 (if present) ++ * QC (if present) ++ */ ++ pos = (u8 *) hdr; ++ aad[0] = 0; /* aad_len >> 8 */ ++ aad[1] = aad_len & 0xff; ++ aad[2] = pos[0] & 0x8f; ++ aad[3] = pos[1] & 0xc7; ++ memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); ++ pos = (u8 *) &hdr->seq_ctl; ++ aad[22] = pos[0] & 0x0f; ++ aad[23] = 0; /* all bits masked */ ++ memset(aad + 24, 0, 8); ++ if (a4_included) ++ memcpy(aad + 24, hdr->addr4, ETH_ALEN); ++ if (qc_included) { ++ aad[a4_included ? 30 : 24] = qc; ++ /* rest of QC masked */ ++ } + -+ /* First try to get the skb from the recycler */ -+#ifdef TITAN_GE_JUMBO_FRAMES -+ skb = titan_ge_alloc_skb(TITAN_GE_JUMBO_BUFSIZE, GFP_ATOMIC); -+#else -+ skb = titan_ge_alloc_skb(TITAN_GE_STD_BUFSIZE, GFP_ATOMIC); ++ /* Start with the first block and AAD */ ++ ieee80211_ccmp_aes_encrypt(tfm, b0, auth); ++ xor_block(auth, aad, AES_BLOCK_LEN); ++ ieee80211_ccmp_aes_encrypt(tfm, auth, auth); ++ xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN); ++ ieee80211_ccmp_aes_encrypt(tfm, auth, auth); ++ b0[0] &= 0x07; ++ b0[14] = b0[15] = 0; ++ ieee80211_ccmp_aes_encrypt(tfm, b0, s0); ++} +#endif -+ if (unlikely(!skb)) { -+ /* OOM, set the flag */ -+ printk("OOM \n"); -+ oom_flag = 1; -+ break; -+ } -+ count++; -+ skb->dev = netdev; -+ -+ titan_ge_port->rx_ring_skbs++; -+ -+ rx_used_desc = titan_ge_port->rx_used_desc_q; -+ rx_desc = &(titan_ge_port->rx_desc_area[rx_used_desc]); + -+#ifdef TITAN_GE_JUMBO_FRAMES -+ rx_desc->buffer_addr = dma_map_single(device, skb->data, -+ TITAN_GE_JUMBO_BUFSIZE - 2, DMA_FROM_DEVICE); -+#else -+ rx_desc->buffer_addr = dma_map_single(device, skb->data, -+ TITAN_GE_STD_BUFSIZE - 2, DMA_FROM_DEVICE); ++static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) ++{ ++ struct ieee80211_ccmp_data *key = priv; ++ int data_len, i; ++ u8 *pos; ++ struct ieee80211_hdr *hdr; ++#ifndef JOHN_CCMP ++ int blocks, last, len; ++ u8 *mic; ++ u8 *b0 = key->tx_b0; ++ u8 *b = key->tx_b; ++ u8 *e = key->tx_e; ++ u8 *s0 = key->tx_s0; +#endif ++ if (skb_headroom(skb) < CCMP_HDR_LEN || ++ skb_tailroom(skb) < CCMP_MIC_LEN || ++ skb->len < hdr_len) ++ return -1; ++ ++ data_len = skb->len - hdr_len; ++ pos = skb_push(skb, CCMP_HDR_LEN); ++ memmove(pos, pos + CCMP_HDR_LEN, hdr_len); ++ pos += hdr_len; ++// mic = skb_put(skb, CCMP_MIC_LEN); + -+ titan_ge_port->rx_skb[rx_used_desc] = skb; -+ rx_desc->cmd_sts = TITAN_GE_RX_BUFFER_OWNED; ++ i = CCMP_PN_LEN - 1; ++ while (i >= 0) { ++ key->tx_pn[i]++; ++ if (key->tx_pn[i] != 0) ++ break; ++ i--; ++ } + -+ titan_ge_port->rx_used_desc_q = -+ (rx_used_desc + 1) % TITAN_GE_RX_QUEUE; ++ *pos++ = key->tx_pn[5]; ++ *pos++ = key->tx_pn[4]; ++ *pos++ = 0; ++ *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */; ++ *pos++ = key->tx_pn[3]; ++ *pos++ = key->tx_pn[2]; ++ *pos++ = key->tx_pn[1]; ++ *pos++ = key->tx_pn[0]; ++ ++ hdr = (struct ieee80211_hdr *) skb->data; ++#ifndef JOHN_CCMP ++ //mic is moved to here by john ++ mic = skb_put(skb, CCMP_MIC_LEN); ++ ++ ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); ++ ++ blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; ++ last = data_len % AES_BLOCK_LEN; ++ ++ for (i = 1; i <= blocks; i++) { ++ len = (i == blocks && last) ? last : AES_BLOCK_LEN; ++ /* Authentication */ ++ xor_block(b, pos, len); ++ ieee80211_ccmp_aes_encrypt(key->tfm, b, b); ++ /* Encryption, with counter */ ++ b0[14] = (i >> 8) & 0xff; ++ b0[15] = i & 0xff; ++ ieee80211_ccmp_aes_encrypt(key->tfm, b0, e); ++ xor_block(pos, e, len); ++ pos += len; + } + -+ return count; ++ for (i = 0; i < CCMP_MIC_LEN; i++) ++ mic[i] = b[i] ^ s0[i]; ++#endif ++ return 0; +} + -+/* -+ * Actual init of the Tital GE port. There is one register for -+ * the channel configuration -+ */ -+static void titan_port_init(struct net_device *netdev, -+ titan_ge_port_info * titan_ge_eth) -+{ -+ unsigned long reg_data; + -+ titan_ge_port_reset(titan_ge_eth->port_num); ++static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) ++{ ++ struct ieee80211_ccmp_data *key = priv; ++ u8 keyidx, *pos; ++ struct ieee80211_hdr *hdr; ++ u8 pn[6]; ++#ifndef JOHN_CCMP ++ size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN; ++ u8 *mic = skb->data + skb->len - CCMP_MIC_LEN; ++ u8 *b0 = key->rx_b0; ++ u8 *b = key->rx_b; ++ u8 *a = key->rx_a; ++ int i, blocks, last, len; ++#endif ++ if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) { ++ key->dot11RSNAStatsCCMPFormatErrors++; ++ return -1; ++ } + -+ /* First reset the TMAC */ -+ reg_data = TITAN_GE_READ(TITAN_GE_CHANNEL0_CONFIG); -+ reg_data |= 0x80000000; -+ TITAN_GE_WRITE(TITAN_GE_CHANNEL0_CONFIG, reg_data); ++ hdr = (struct ieee80211_hdr *) skb->data; ++ pos = skb->data + hdr_len; ++ keyidx = pos[3]; ++ if (!(keyidx & (1 << 5))) { ++ if (net_ratelimit()) { ++ printk(KERN_DEBUG "CCMP: received packet without ExtIV" ++ " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2)); ++ } ++ key->dot11RSNAStatsCCMPFormatErrors++; ++ return -2; ++ } ++ keyidx >>= 6; ++ if (key->key_idx != keyidx) { ++ printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame " ++ "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv); ++ return -6; ++ } ++ if (!key->key_set) { ++ if (net_ratelimit()) { ++ printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT ++ " with keyid=%d that does not have a configured" ++ " key\n", MAC_ARG(hdr->addr2), keyidx); ++ } ++ return -3; ++ } + -+ udelay(30); ++ pn[0] = pos[7]; ++ pn[1] = pos[6]; ++ pn[2] = pos[5]; ++ pn[3] = pos[4]; ++ pn[4] = pos[1]; ++ pn[5] = pos[0]; ++ pos += 8; ++#if 0 ++ if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) { ++ if (net_ratelimit()) { ++ printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT ++ " previous PN %02x%02x%02x%02x%02x%02x " ++ "received PN %02x%02x%02x%02x%02x%02x\n", ++ MAC_ARG(hdr->addr2), MAC_ARG(key->rx_pn), ++ MAC_ARG(pn)); ++ } ++ key->dot11RSNAStatsCCMPReplays++; ++ return -4; ++ } ++#endif ++#ifndef JOHN_CCMP ++ ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b); ++ xor_block(mic, b, CCMP_MIC_LEN); ++ ++ blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; ++ last = data_len % AES_BLOCK_LEN; ++ ++ for (i = 1; i <= blocks; i++) { ++ len = (i == blocks && last) ? last : AES_BLOCK_LEN; ++ /* Decrypt, with counter */ ++ b0[14] = (i >> 8) & 0xff; ++ b0[15] = i & 0xff; ++ ieee80211_ccmp_aes_encrypt(key->tfm, b0, b); ++ xor_block(pos, b, len); ++ /* Authentication */ ++ xor_block(a, pos, len); ++ ieee80211_ccmp_aes_encrypt(key->tfm, a, a); ++ pos += len; ++ } + -+ reg_data = TITAN_GE_READ(TITAN_GE_CHANNEL0_CONFIG); -+ reg_data &= ~(0xc0000000); -+ TITAN_GE_WRITE(TITAN_GE_CHANNEL0_CONFIG, reg_data); ++ if (memcmp(mic, a, CCMP_MIC_LEN) != 0) { ++ if (net_ratelimit()) { ++ printk(KERN_DEBUG "CCMP: decrypt failed: STA=" ++ MAC_FMT "\n", MAC_ARG(hdr->addr2)); ++ } ++ key->dot11RSNAStatsCCMPDecryptErrors++; ++ return -5; ++ } + -+ /* Now reset the RMAC */ -+ reg_data = TITAN_GE_READ(TITAN_GE_CHANNEL0_CONFIG); -+ reg_data |= 0x00080000; -+ TITAN_GE_WRITE(TITAN_GE_CHANNEL0_CONFIG, reg_data); ++ memcpy(key->rx_pn, pn, CCMP_PN_LEN); + -+ udelay(30); ++#endif ++ /* Remove hdr and MIC */ ++ memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len); ++ skb_pull(skb, CCMP_HDR_LEN); ++ skb_trim(skb, skb->len - CCMP_MIC_LEN); + -+ reg_data = TITAN_GE_READ(TITAN_GE_CHANNEL0_CONFIG); -+ reg_data &= ~(0x000c0000); -+ TITAN_GE_WRITE(TITAN_GE_CHANNEL0_CONFIG, reg_data); ++ return keyidx; +} + -+/* -+ * Start the port. All the hardware specific configuration -+ * for the XDMA, Tx FIFO, Rx FIFO, TMAC, RMAC, TRTG and AFX -+ * go here -+ */ -+static int titan_ge_port_start(struct net_device *netdev, -+ titan_ge_port_info * titan_port) ++ ++static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv) +{ -+ volatile unsigned long reg_data, reg_data1; -+ int port_num = titan_port->port_num; -+ int count = 0; -+ unsigned long reg_data_1; ++ struct ieee80211_ccmp_data *data = priv; ++ int keyidx; ++ struct crypto_tfm *tfm = data->tfm; ++ ++ keyidx = data->key_idx; ++ memset(data, 0, sizeof(*data)); ++ data->key_idx = keyidx; ++ data->tfm = tfm; ++ if (len == CCMP_TK_LEN) { ++ memcpy(data->key, key, CCMP_TK_LEN); ++ data->key_set = 1; ++ if (seq) { ++ data->rx_pn[0] = seq[5]; ++ data->rx_pn[1] = seq[4]; ++ data->rx_pn[2] = seq[3]; ++ data->rx_pn[3] = seq[2]; ++ data->rx_pn[4] = seq[1]; ++ data->rx_pn[5] = seq[0]; ++ } ++ crypto_cipher_setkey((void*)data->tfm, data->key, CCMP_TK_LEN); ++ } else if (len == 0) ++ data->key_set = 0; ++ else ++ return -1; + -+ if (config_done == 0) { -+ reg_data = TITAN_GE_READ(0x0004); -+ reg_data |= 0x100; -+ TITAN_GE_WRITE(0x0004, reg_data); ++ return 0; ++} + -+ reg_data &= ~(0x100); -+ TITAN_GE_WRITE(0x0004, reg_data); + -+ /* Turn on GMII/MII mode and turn off TBI mode */ -+ reg_data = TITAN_GE_READ(TITAN_GE_TSB_CTRL_1); -+ reg_data |= 0x00000700; -+ reg_data &= ~(0x00800000); /* Fencing */ ++static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv) ++{ ++ struct ieee80211_ccmp_data *data = priv; + -+ TITAN_GE_WRITE(0x000c, 0x00001100); ++ if (len < CCMP_TK_LEN) ++ return -1; + -+ TITAN_GE_WRITE(TITAN_GE_TSB_CTRL_1, reg_data); ++ if (!data->key_set) ++ return 0; ++ memcpy(key, data->key, CCMP_TK_LEN); ++ ++ if (seq) { ++ seq[0] = data->tx_pn[5]; ++ seq[1] = data->tx_pn[4]; ++ seq[2] = data->tx_pn[3]; ++ seq[3] = data->tx_pn[2]; ++ seq[4] = data->tx_pn[1]; ++ seq[5] = data->tx_pn[0]; ++ } + -+ /* Set the CPU Resource Limit register */ -+ TITAN_GE_WRITE(0x00f8, 0x8); ++ return CCMP_TK_LEN; ++} + -+ /* Be conservative when using the BIU buffers */ -+ TITAN_GE_WRITE(0x0068, 0x4); -+ } + -+ titan_port->tx_threshold = 0; -+ titan_port->rx_threshold = 0; ++static char * ieee80211_ccmp_print_stats(char *p, void *priv) ++{ ++ struct ieee80211_ccmp_data *ccmp = priv; ++ p += sprintf(p, "key[%d] alg=CCMP key_set=%d " ++ "tx_pn=%02x%02x%02x%02x%02x%02x " ++ "rx_pn=%02x%02x%02x%02x%02x%02x " ++ "format_errors=%d replays=%d decrypt_errors=%d\n", ++ ccmp->key_idx, ccmp->key_set, ++ MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn), ++ ccmp->dot11RSNAStatsCCMPFormatErrors, ++ ccmp->dot11RSNAStatsCCMPReplays, ++ ccmp->dot11RSNAStatsCCMPDecryptErrors); ++ ++ return p; ++} + -+ /* We need to write the descriptors for Tx and Rx */ -+ TITAN_GE_WRITE((TITAN_GE_CHANNEL0_TX_DESC + (port_num << 8)), -+ (unsigned long) titan_port->tx_dma); -+ TITAN_GE_WRITE((TITAN_GE_CHANNEL0_RX_DESC + (port_num << 8)), -+ (unsigned long) titan_port->rx_dma); ++void ieee80211_ccmp_null(void) ++{ ++ // printk("============>%s()\n", __FUNCTION__); ++ return; ++} ++static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = { ++ .name = "CCMP", ++ .init = ieee80211_ccmp_init, ++ .deinit = ieee80211_ccmp_deinit, ++ .encrypt_mpdu = ieee80211_ccmp_encrypt, ++ .decrypt_mpdu = ieee80211_ccmp_decrypt, ++ .encrypt_msdu = NULL, ++ .decrypt_msdu = NULL, ++ .set_key = ieee80211_ccmp_set_key, ++ .get_key = ieee80211_ccmp_get_key, ++ .print_stats = ieee80211_ccmp_print_stats, ++ .extra_prefix_len = CCMP_HDR_LEN, ++ .extra_postfix_len = CCMP_MIC_LEN, ++ .owner = THIS_MODULE, ++}; + -+ if (config_done == 0) { -+ /* Step 1: XDMA config */ -+ reg_data = TITAN_GE_READ(TITAN_GE_XDMA_CONFIG); -+ reg_data &= ~(0x80000000); /* clear reset */ -+ reg_data |= 0x1 << 29; /* sparse tx descriptor spacing */ -+ reg_data |= 0x1 << 28; /* sparse rx descriptor spacing */ -+ reg_data |= (0x1 << 23) | (0x1 << 24); /* Descriptor Coherency */ -+ reg_data |= (0x1 << 21) | (0x1 << 22); /* Data Coherency */ -+ TITAN_GE_WRITE(TITAN_GE_XDMA_CONFIG, reg_data); -+ } + -+ /* IR register for the XDMA */ -+ reg_data = TITAN_GE_READ(TITAN_GE_GDI_INTERRUPT_ENABLE + (port_num << 8)); -+ reg_data |= 0x80068000; /* No Rx_OOD */ -+ TITAN_GE_WRITE((TITAN_GE_GDI_INTERRUPT_ENABLE + (port_num << 8)), reg_data); ++int __init ieee80211_crypto_ccmp_init(void) ++{ ++ return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp); ++} + -+ /* Start the Tx and Rx XDMA controller */ -+ reg_data = TITAN_GE_READ(TITAN_GE_CHANNEL0_CONFIG + (port_num << 8)); -+ reg_data &= 0x4fffffff; /* Clear tx reset */ -+ reg_data &= 0xfff4ffff; /* Clear rx reset */ + -+#ifdef TITAN_GE_JUMBO_FRAMES -+ reg_data |= 0xa0 | 0x30030000; ++void __exit ieee80211_crypto_ccmp_exit(void) ++{ ++ ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp); ++} ++#if 0 ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++EXPORT_SYMBOL(ieee80211_ccmp_null); +#else -+ reg_data |= 0x40 | 0x20030000; ++EXPORT_SYMBOL_NOVERS(ieee80211_ccmp_null); +#endif + -+#ifndef CONFIG_SMP -+ reg_data &= ~(0x10); -+ reg_data |= 0x0f; /* All of the packet */ ++module_init(ieee80211_crypto_ccmp_init); ++module_exit(ieee80211_crypto_ccmp_exit); +#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,91 @@ ++/* ++ * Original code based on Host AP (software wireless LAN access point) driver ++ * for Intersil Prism2/2.5/3. ++ * ++ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen ++ * ++ * Copyright (c) 2002-2003, Jouni Malinen ++ * ++ * Adaption to a generic IEEE 802.11 stack by James Ketrenos ++ * ++ * ++ * Copyright (c) 2004, Intel Corporation ++ * ++ * 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. See README and COPYING for ++ * more details. ++ */ + -+ TITAN_GE_WRITE((TITAN_GE_CHANNEL0_CONFIG + (port_num << 8)), reg_data); -+ -+ /* Rx desc count */ -+ count = titan_ge_rx_task(netdev, titan_port); -+ TITAN_GE_WRITE((0x5048 + (port_num << 8)), count); -+ count = TITAN_GE_READ(0x5048 + (port_num << 8)); -+ -+ udelay(30); -+ -+ /* -+ * Step 2: Configure the SDQPF, i.e. FIFO -+ */ -+ if (config_done == 0) { -+ reg_data = TITAN_GE_READ(TITAN_GE_SDQPF_RXFIFO_CTL); -+ reg_data = 0x1; -+ TITAN_GE_WRITE(TITAN_GE_SDQPF_RXFIFO_CTL, reg_data); -+ reg_data &= ~(0x1); -+ TITAN_GE_WRITE(TITAN_GE_SDQPF_RXFIFO_CTL, reg_data); -+ reg_data = TITAN_GE_READ(TITAN_GE_SDQPF_RXFIFO_CTL); -+ TITAN_GE_WRITE(TITAN_GE_SDQPF_RXFIFO_CTL, reg_data); -+ -+ reg_data = TITAN_GE_READ(TITAN_GE_SDQPF_TXFIFO_CTL); -+ reg_data = 0x1; -+ TITAN_GE_WRITE(TITAN_GE_SDQPF_TXFIFO_CTL, reg_data); -+ reg_data &= ~(0x1); -+ TITAN_GE_WRITE(TITAN_GE_SDQPF_TXFIFO_CTL, reg_data); -+ reg_data = TITAN_GE_READ(TITAN_GE_SDQPF_TXFIFO_CTL); -+ TITAN_GE_WRITE(TITAN_GE_SDQPF_TXFIFO_CTL, reg_data); -+ } -+ /* -+ * Enable RX FIFO 0, 4 and 8 -+ */ -+ if (port_num == 0) { -+ reg_data = TITAN_GE_READ(TITAN_GE_SDQPF_RXFIFO_0); -+ -+ reg_data |= 0x100000; -+ reg_data |= (0xff << 10); -+ -+ TITAN_GE_WRITE(TITAN_GE_SDQPF_RXFIFO_0, reg_data); -+ /* -+ * BAV2,BAV and DAV settings for the Rx FIFO -+ */ -+ reg_data1 = TITAN_GE_READ(0x4844); -+ reg_data1 |= ( (0x10 << 20) | (0x10 << 10) | 0x1); -+ TITAN_GE_WRITE(0x4844, reg_data1); -+ -+ reg_data &= ~(0x00100000); -+ reg_data |= 0x200000; -+ -+ TITAN_GE_WRITE(TITAN_GE_SDQPF_RXFIFO_0, reg_data); ++/* ++ * This file defines the interface to the ieee80211 crypto module. ++ */ ++#ifndef IEEE80211_CRYPT_H ++#define IEEE80211_CRYPT_H + -+ reg_data = TITAN_GE_READ(TITAN_GE_SDQPF_TXFIFO_0); -+ reg_data |= 0x100000; ++#include + -+ TITAN_GE_WRITE(TITAN_GE_SDQPF_TXFIFO_0, reg_data); ++struct ieee80211_crypto_ops { ++ const char *name; + -+ reg_data |= (0xff << 10); ++ /* init new crypto context (e.g., allocate private data space, ++ * select IV, etc.); returns NULL on failure or pointer to allocated ++ * private data on success */ ++ void * (*init)(int keyidx); + -+ TITAN_GE_WRITE(TITAN_GE_SDQPF_TXFIFO_0, reg_data); ++ /* deinitialize crypto context and free allocated private data */ ++ void (*deinit)(void *priv); + -+ /* -+ * BAV2, BAV and DAV settings for the Tx FIFO -+ */ -+ reg_data1 = TITAN_GE_READ(0x4944); -+ reg_data1 = ( (0x1 << 20) | (0x1 << 10) | 0x10); ++ /* encrypt/decrypt return < 0 on error or >= 0 on success. The return ++ * value from decrypt_mpdu is passed as the keyidx value for ++ * decrypt_msdu. skb must have enough head and tail room for the ++ * encryption; if not, error will be returned; these functions are ++ * called for all MPDUs (i.e., fragments). ++ */ ++ int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); ++ int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); + -+ TITAN_GE_WRITE(0x4944, reg_data1); ++ /* These functions are called for full MSDUs, i.e. full frames. ++ * These can be NULL if full MSDU operations are not needed. */ ++ int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv); ++ int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len, ++ void *priv); + -+ reg_data &= ~(0x00100000); -+ reg_data |= 0x200000; ++ int (*set_key)(void *key, int len, u8 *seq, void *priv); ++ int (*get_key)(void *key, int len, u8 *seq, void *priv); + -+ TITAN_GE_WRITE(TITAN_GE_SDQPF_TXFIFO_0, reg_data); ++ /* procfs handler for printing out key information and possible ++ * statistics */ ++ char * (*print_stats)(char *p, void *priv); + -+ } ++ /* maximum number of bytes added by encryption; encrypt buf is ++ * allocated with extra_prefix_len bytes, copy of in_buf, and ++ * extra_postfix_len; encrypt need not use all this space, but ++ * the result must start at the beginning of the buffer and correct ++ * length must be returned */ ++ int extra_prefix_len, extra_postfix_len; + -+ if (port_num == 1) { -+ reg_data = TITAN_GE_READ(0x4870); ++ struct module *owner; ++}; + -+ reg_data |= 0x100000; -+ reg_data |= (0xff << 10) | (0xff + 1); ++struct ieee80211_crypt_data { ++ struct list_head list; /* delayed deletion list */ ++ struct ieee80211_crypto_ops *ops; ++ void *priv; ++ atomic_t refcnt; ++}; + -+ TITAN_GE_WRITE(0x4870, reg_data); -+ /* -+ * BAV2,BAV and DAV settings for the Rx FIFO -+ */ -+ reg_data1 = TITAN_GE_READ(0x4874); -+ reg_data1 |= ( (0x10 << 20) | (0x10 << 10) | 0x1); -+ TITAN_GE_WRITE(0x4874, reg_data1); ++int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops); ++int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops); ++struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name); ++void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int); ++void ieee80211_crypt_deinit_handler(unsigned long); ++void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, ++ struct ieee80211_crypt_data **crypt); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) ++#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK) ++#define crypto_alloc_tfm crypto_alloc_tfm_rtl ++#define crypto_free_tfm crypto_free_tfm_rtl ++#endif + -+ reg_data &= ~(0x00100000); -+ reg_data |= 0x200000; ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt_tkip.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt_tkip.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt_tkip.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt_tkip.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,996 @@ ++/* ++ * Host AP crypt: host-based TKIP encryption implementation for Host AP driver ++ * ++ * Copyright (c) 2003-2004, Jouni Malinen ++ * ++ * 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. See README and COPYING for ++ * more details. ++ */ + -+ TITAN_GE_WRITE(0x4870, reg_data); ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+ reg_data = TITAN_GE_READ(0x494c); -+ reg_data |= 0x100000; ++#include "ieee80211.h" + -+ TITAN_GE_WRITE(0x494c, reg_data); -+ reg_data |= (0xff << 10) | (0xff + 1); -+ TITAN_GE_WRITE(0x494c, reg_data); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) ++#include "rtl_crypto.h" ++#else ++#include ++#endif ++//#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ #include ++#else ++ #include ++#endif + -+ /* -+ * BAV2, BAV and DAV settings for the Tx FIFO -+ */ -+ reg_data1 = TITAN_GE_READ(0x4950); -+ reg_data1 = ( (0x1 << 20) | (0x1 << 10) | 0x10); ++#include + -+ TITAN_GE_WRITE(0x4950, reg_data1); ++MODULE_AUTHOR("Jouni Malinen"); ++MODULE_DESCRIPTION("Host AP crypt: TKIP"); ++MODULE_LICENSE("GPL"); + -+ reg_data &= ~(0x00100000); -+ reg_data |= 0x200000; ++struct ieee80211_tkip_data { ++#define TKIP_KEY_LEN 32 ++ u8 key[TKIP_KEY_LEN]; ++ int key_set; ++ ++ u32 tx_iv32; ++ u16 tx_iv16; ++ u16 tx_ttak[5]; ++ int tx_phase1_done; ++ ++ u32 rx_iv32; ++ u16 rx_iv16; ++ u16 rx_ttak[5]; ++ int rx_phase1_done; ++ u32 rx_iv32_new; ++ u16 rx_iv16_new; ++ ++ u32 dot11RSNAStatsTKIPReplays; ++ u32 dot11RSNAStatsTKIPICVErrors; ++ u32 dot11RSNAStatsTKIPLocalMICFailures; ++ ++ int key_idx; ++ ++ #if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) ++ struct crypto_blkcipher *rx_tfm_arc4; ++ struct crypto_hash *rx_tfm_michael; ++ struct crypto_blkcipher *tx_tfm_arc4; ++ struct crypto_hash *tx_tfm_michael; ++ #endif ++ ++ struct crypto_tfm *tfm_arc4; ++ struct crypto_tfm *tfm_michael; ++ ++ /* scratch buffers for virt_to_page() (crypto API) */ ++ u8 rx_hdr[16], tx_hdr[16]; ++}; + -+ TITAN_GE_WRITE(0x494c, reg_data); ++static void * ieee80211_tkip_init(int key_idx) ++{ ++ struct ieee80211_tkip_data *priv; ++ ++ priv = kmalloc(sizeof(*priv), GFP_ATOMIC); ++ if (priv == NULL) ++ goto fail; ++ memset(priv, 0, sizeof(*priv)); ++ priv->key_idx = key_idx; ++ ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0); ++ if (priv->tfm_arc4 == NULL) { ++ printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " ++ "crypto API arc4\n"); ++ goto fail; + } + -+ /* -+ * Titan 1.2 revision does support port #2 -+ */ -+ if (port_num == 2) { -+ /* -+ * Put the descriptors in the SRAM -+ */ -+ reg_data = TITAN_GE_READ(0x48a0); -+ -+ reg_data |= 0x100000; -+ reg_data |= (0xff << 10) | (2*(0xff + 1)); -+ -+ TITAN_GE_WRITE(0x48a0, reg_data); -+ /* -+ * BAV2,BAV and DAV settings for the Rx FIFO -+ */ -+ reg_data1 = TITAN_GE_READ(0x48a4); -+ reg_data1 |= ( (0x10 << 20) | (0x10 << 10) | 0x1); -+ TITAN_GE_WRITE(0x48a4, reg_data1); -+ -+ reg_data &= ~(0x00100000); -+ reg_data |= 0x200000; ++ priv->tfm_michael = crypto_alloc_tfm("michael_mic", 0); ++ if (priv->tfm_michael == NULL) { ++ printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " ++ "crypto API michael_mic\n"); ++ goto fail; ++ } + -+ TITAN_GE_WRITE(0x48a0, reg_data); ++ #else ++ priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, ++ CRYPTO_ALG_ASYNC); ++ if (IS_ERR(priv->tx_tfm_arc4)) { ++ printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " ++ "crypto API arc4\n"); ++ priv->tx_tfm_arc4 = NULL; ++ goto fail; ++ } + -+ reg_data = TITAN_GE_READ(0x4958); -+ reg_data |= 0x100000; ++ priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, ++ CRYPTO_ALG_ASYNC); ++ if (IS_ERR(priv->tx_tfm_michael)) { ++ printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " ++ "crypto API michael_mic\n"); ++ priv->tx_tfm_michael = NULL; ++ goto fail; ++ } + -+ TITAN_GE_WRITE(0x4958, reg_data); -+ reg_data |= (0xff << 10) | (2*(0xff + 1)); -+ TITAN_GE_WRITE(0x4958, reg_data); ++ priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, ++ CRYPTO_ALG_ASYNC); ++ if (IS_ERR(priv->rx_tfm_arc4)) { ++ printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " ++ "crypto API arc4\n"); ++ priv->rx_tfm_arc4 = NULL; ++ goto fail; ++ } + -+ /* -+ * BAV2, BAV and DAV settings for the Tx FIFO -+ */ -+ reg_data1 = TITAN_GE_READ(0x495c); -+ reg_data1 = ( (0x1 << 20) | (0x1 << 10) | 0x10); ++ priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, ++ CRYPTO_ALG_ASYNC); ++ if (IS_ERR(priv->rx_tfm_michael)) { ++ printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " ++ "crypto API michael_mic\n"); ++ priv->rx_tfm_michael = NULL; ++ goto fail; ++ } ++ #endif ++ return priv; ++ ++fail: ++ if (priv) { ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ if (priv->tfm_michael) ++ crypto_free_tfm(priv->tfm_michael); ++ if (priv->tfm_arc4) ++ crypto_free_tfm(priv->tfm_arc4); ++ #else ++ if (priv->tx_tfm_michael) ++ crypto_free_hash(priv->tx_tfm_michael); ++ if (priv->tx_tfm_arc4) ++ crypto_free_blkcipher(priv->tx_tfm_arc4); ++ if (priv->rx_tfm_michael) ++ crypto_free_hash(priv->rx_tfm_michael); ++ if (priv->rx_tfm_arc4) ++ crypto_free_blkcipher(priv->rx_tfm_arc4); ++ #endif ++ kfree(priv); ++ } + -+ TITAN_GE_WRITE(0x495c, reg_data1); ++ return NULL; ++} + -+ reg_data &= ~(0x00100000); -+ reg_data |= 0x200000; + -+ TITAN_GE_WRITE(0x4958, reg_data); ++static void ieee80211_tkip_deinit(void *priv) ++{ ++ struct ieee80211_tkip_data *_priv = priv; ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ if (_priv && _priv->tfm_michael) ++ crypto_free_tfm(_priv->tfm_michael); ++ if (_priv && _priv->tfm_arc4) ++ crypto_free_tfm(_priv->tfm_arc4); ++ #else ++ if (_priv) { ++ if (_priv->tx_tfm_michael) ++ crypto_free_hash(_priv->tx_tfm_michael); ++ if (_priv->tx_tfm_arc4) ++ crypto_free_blkcipher(_priv->tx_tfm_arc4); ++ if (_priv->rx_tfm_michael) ++ crypto_free_hash(_priv->rx_tfm_michael); ++ if (_priv->rx_tfm_arc4) ++ crypto_free_blkcipher(_priv->rx_tfm_arc4); + } ++ #endif ++ kfree(priv); ++} + -+ if (port_num == 2) { -+ reg_data = TITAN_GE_READ(0x48a0); -+ -+ reg_data |= 0x100000; -+ reg_data |= (0xff << 10) | (2*(0xff + 1)); + -+ TITAN_GE_WRITE(0x48a0, reg_data); -+ /* -+ * BAV2,BAV and DAV settings for the Rx FIFO -+ */ -+ reg_data1 = TITAN_GE_READ(0x48a4); -+ reg_data1 |= ( (0x10 << 20) | (0x10 << 10) | 0x1); -+ TITAN_GE_WRITE(0x48a4, reg_data1); ++static inline u16 RotR1(u16 val) ++{ ++ return (val >> 1) | (val << 15); ++} + -+ reg_data &= ~(0x00100000); -+ reg_data |= 0x200000; + -+ TITAN_GE_WRITE(0x48a0, reg_data); ++static inline u8 Lo8(u16 val) ++{ ++ return val & 0xff; ++} + -+ reg_data = TITAN_GE_READ(0x4958); -+ reg_data |= 0x100000; + -+ TITAN_GE_WRITE(0x4958, reg_data); -+ reg_data |= (0xff << 10) | (2*(0xff + 1)); -+ TITAN_GE_WRITE(0x4958, reg_data); ++static inline u8 Hi8(u16 val) ++{ ++ return val >> 8; ++} + -+ /* -+ * BAV2, BAV and DAV settings for the Tx FIFO -+ */ -+ reg_data1 = TITAN_GE_READ(0x495c); -+ reg_data1 = ( (0x1 << 20) | (0x1 << 10) | 0x10); + -+ TITAN_GE_WRITE(0x495c, reg_data1); ++static inline u16 Lo16(u32 val) ++{ ++ return val & 0xffff; ++} + -+ reg_data &= ~(0x00100000); -+ reg_data |= 0x200000; + -+ TITAN_GE_WRITE(0x4958, reg_data); -+ } ++static inline u16 Hi16(u32 val) ++{ ++ return val >> 16; ++} + -+ /* -+ * Step 3: TRTG block enable -+ */ -+ reg_data = TITAN_GE_READ(TITAN_GE_TRTG_CONFIG + (port_num << 12)); + -+ /* -+ * This is the 1.2 revision of the chip. It has fix for the -+ * IP header alignment. Now, the IP header begins at an -+ * aligned address and this wont need an extra copy in the -+ * driver. This performance drawback existed in the previous -+ * versions of the silicon -+ */ -+ reg_data_1 = TITAN_GE_READ(0x103c + (port_num << 12)); -+ reg_data_1 |= 0x40000000; -+ TITAN_GE_WRITE((0x103c + (port_num << 12)), reg_data_1); ++static inline u16 Mk16(u8 hi, u8 lo) ++{ ++ return lo | (((u16) hi) << 8); ++} + -+ reg_data_1 |= 0x04000000; -+ TITAN_GE_WRITE((0x103c + (port_num << 12)), reg_data_1); + -+ mdelay(5); ++static inline u16 Mk16_le(u16 *v) ++{ ++ return le16_to_cpu(*v); ++} + -+ reg_data_1 &= ~(0x04000000); -+ TITAN_GE_WRITE((0x103c + (port_num << 12)), reg_data_1); + -+ mdelay(5); ++static const u16 Sbox[256] = ++{ ++ 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, ++ 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, ++ 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, ++ 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, ++ 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, ++ 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, ++ 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, ++ 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, ++ 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, ++ 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, ++ 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, ++ 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, ++ 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, ++ 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, ++ 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, ++ 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, ++ 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, ++ 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, ++ 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, ++ 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, ++ 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, ++ 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, ++ 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, ++ 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, ++ 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, ++ 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, ++ 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, ++ 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, ++ 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, ++ 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, ++ 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, ++ 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, ++}; + -+ reg_data |= 0x0001; -+ TITAN_GE_WRITE((TITAN_GE_TRTG_CONFIG + (port_num << 12)), reg_data); + -+ /* -+ * Step 4: Start the Tx activity -+ */ -+ TITAN_GE_WRITE((TITAN_GE_TMAC_CONFIG_2 + (port_num << 12)), 0xe197); -+#ifdef TITAN_GE_JUMBO_FRAMES -+ TITAN_GE_WRITE((0x1258 + (port_num << 12)), 0x4000); -+#endif -+ reg_data = TITAN_GE_READ(TITAN_GE_TMAC_CONFIG_1 + (port_num << 12)); -+ reg_data |= 0x0001; /* Enable TMAC */ -+ reg_data |= 0x6c70; /* PAUSE also set */ ++static inline u16 _S_(u16 v) ++{ ++ u16 t = Sbox[Hi8(v)]; ++ return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8)); ++} + -+ TITAN_GE_WRITE((TITAN_GE_TMAC_CONFIG_1 + (port_num << 12)), reg_data); ++#ifndef JOHN_TKIP ++#define PHASE1_LOOP_COUNT 8 + -+ udelay(30); ++static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32) ++{ ++ int i, j; ++ ++ /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */ ++ TTAK[0] = Lo16(IV32); ++ TTAK[1] = Hi16(IV32); ++ TTAK[2] = Mk16(TA[1], TA[0]); ++ TTAK[3] = Mk16(TA[3], TA[2]); ++ TTAK[4] = Mk16(TA[5], TA[4]); ++ ++ for (i = 0; i < PHASE1_LOOP_COUNT; i++) { ++ j = 2 * (i & 1); ++ TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j])); ++ TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j])); ++ TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j])); ++ TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j])); ++ TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i; ++ } ++} + -+ /* Destination Address drop bit */ -+ reg_data = TITAN_GE_READ(TITAN_GE_RMAC_CONFIG_2 + (port_num << 12)); -+ reg_data |= 0x218; /* DA_DROP bit and pause */ -+ TITAN_GE_WRITE((TITAN_GE_RMAC_CONFIG_2 + (port_num << 12)), reg_data); + -+ TITAN_GE_WRITE((0x1218 + (port_num << 12)), 0x3); ++static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, ++ u16 IV16) ++{ ++ /* Make temporary area overlap WEP seed so that the final copy can be ++ * avoided on little endian hosts. */ ++ u16 *PPK = (u16 *) &WEPSeed[4]; ++ ++ /* Step 1 - make copy of TTAK and bring in TSC */ ++ PPK[0] = TTAK[0]; ++ PPK[1] = TTAK[1]; ++ PPK[2] = TTAK[2]; ++ PPK[3] = TTAK[3]; ++ PPK[4] = TTAK[4]; ++ PPK[5] = TTAK[4] + IV16; ++ ++ /* Step 2 - 96-bit bijective mixing using S-box */ ++ PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0])); ++ PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2])); ++ PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4])); ++ PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6])); ++ PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8])); ++ PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10])); ++ ++ PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12])); ++ PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14])); ++ PPK[2] += RotR1(PPK[1]); ++ PPK[3] += RotR1(PPK[2]); ++ PPK[4] += RotR1(PPK[3]); ++ PPK[5] += RotR1(PPK[4]); ++ ++ /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value ++ * WEPSeed[0..2] is transmitted as WEP IV */ ++ WEPSeed[0] = Hi8(IV16); ++ WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F; ++ WEPSeed[2] = Lo8(IV16); ++ WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1); + -+#ifdef TITAN_GE_JUMBO_FRAMES -+ TITAN_GE_WRITE((0x1208 + (port_num << 12)), 0x4000); ++#ifdef __BIG_ENDIAN ++ { ++ int i; ++ for (i = 0; i < 6; i++) ++ PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8); ++ } +#endif -+ /* Start the Rx activity */ -+ reg_data = TITAN_GE_READ(TITAN_GE_RMAC_CONFIG_1 + (port_num << 12)); -+ reg_data |= 0x0001; /* RMAC Enable */ -+ reg_data |= 0x0010; /* CRC Check enable */ -+ reg_data |= 0x0040; /* Min Frame check enable */ -+ reg_data |= 0x4400; /* Max Frame check enable */ -+ -+ TITAN_GE_WRITE((TITAN_GE_RMAC_CONFIG_1 + (port_num << 12)), reg_data); ++} ++#endif ++static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) ++{ ++ struct ieee80211_tkip_data *tkey = priv; ++ #if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) ++ struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4}; ++ #endif ++ int len; ++ u8 *pos; ++ struct ieee80211_hdr *hdr; ++#ifndef JOHN_TKIP ++ u8 rc4key[16],*icv; ++ u32 crc; ++ struct scatterlist sg; ++#endif ++ #if(LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,21)) ++ int ret; ++ #endif ++ ++ if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 || ++ skb->len < hdr_len) ++ return -1; + -+ udelay(30); ++ hdr = (struct ieee80211_hdr *) skb->data; ++#if 0 ++printk("@@ tkey\n"); ++printk("%x|", ((u32*)tkey->key)[0]); ++printk("%x|", ((u32*)tkey->key)[1]); ++printk("%x|", ((u32*)tkey->key)[2]); ++printk("%x|", ((u32*)tkey->key)[3]); ++printk("%x|", ((u32*)tkey->key)[4]); ++printk("%x|", ((u32*)tkey->key)[5]); ++printk("%x|", ((u32*)tkey->key)[6]); ++printk("%x\n", ((u32*)tkey->key)[7]); ++#endif + -+ /* -+ * Enable the Interrupts for Tx and Rx -+ */ -+ reg_data1 = TITAN_GE_READ(TITAN_GE_INTR_XDMA_IE); ++#ifndef JOHN_TKIP ++ if (!tkey->tx_phase1_done) { ++ tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, ++ tkey->tx_iv32); ++ tkey->tx_phase1_done = 1; ++ } ++ tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); + -+ if (port_num == 0) { -+ reg_data1 |= 0x3; -+#ifdef CONFIG_SMP -+ TITAN_GE_WRITE(0x0038, 0x003); +#else -+ TITAN_GE_WRITE(0x0038, 0x303); ++ tkey->tx_phase1_done = 1; ++#endif /*JOHN_TKIP*/ ++ ++ len = skb->len - hdr_len; ++ pos = skb_push(skb, 8); ++ memmove(pos, pos + 8, hdr_len); ++ pos += hdr_len; ++ ++#ifdef JOHN_TKIP ++ *pos++ = Hi8(tkey->tx_iv16); ++ *pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F; ++ *pos++ = Lo8(tkey->tx_iv16); ++#else ++ *pos++ = rc4key[0]; ++ *pos++ = rc4key[1]; ++ *pos++ = rc4key[2]; +#endif ++ *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */; ++ *pos++ = tkey->tx_iv32 & 0xff; ++ *pos++ = (tkey->tx_iv32 >> 8) & 0xff; ++ *pos++ = (tkey->tx_iv32 >> 16) & 0xff; ++ *pos++ = (tkey->tx_iv32 >> 24) & 0xff; ++#ifndef JOHN_TKIP ++ icv = skb_put(skb, 4); ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++ crc = ~crc32_le(~0, pos, len); ++#else ++ crc = ~ether_crc_le(len, pos); ++#endif ++ icv[0] = crc; ++ icv[1] = crc >> 8; ++ icv[2] = crc >> 16; ++ icv[3] = crc >> 24; ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); ++ sg.page = virt_to_page(pos); ++ sg.offset = offset_in_page(pos); ++ sg.length = len + 4; ++ crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4); ++ #else ++ crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) ++ sg.page = virt_to_page(pos); ++ sg.offset = offset_in_page(pos); ++ sg.length = len + 4; ++ #else ++ sg_init_one(&sg, pos, len + 4); ++ #endif ++ ret= crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); ++ #endif ++#endif ++ tkey->tx_iv16++; ++ if (tkey->tx_iv16 == 0) { ++ tkey->tx_phase1_done = 0; ++ tkey->tx_iv32++; + } ++#ifndef JOHN_TKIP ++ #if(LINUX_VERSION_CODE = KERNEL_VERSION(2,6,21)) ++ struct blkcipher_desc desc = {.tfm = tkey->rx_tfm_arc4}; ++ #endif ++ u8 keyidx, *pos; ++ u32 iv32; ++ u16 iv16; ++ struct ieee80211_hdr *hdr; ++#ifndef JOHN_TKIP ++ u8 icv[4]; ++ u32 crc; ++ struct scatterlist sg; ++ u8 rc4key[16]; ++ int plen; ++#endif ++ if (skb->len < hdr_len + 8 + 4) ++ return -1; + -+ if (config_done == 0) { -+ TITAN_GE_WRITE(0x0024, 0x04000024); /* IRQ vector */ -+ TITAN_GE_WRITE(0x0020, 0x000fb000); /* INTMSG base */ ++ hdr = (struct ieee80211_hdr *) skb->data; ++ pos = skb->data + hdr_len; ++ keyidx = pos[3]; ++ if (!(keyidx & (1 << 5))) { ++ if (net_ratelimit()) { ++ printk(KERN_DEBUG "TKIP: received packet without ExtIV" ++ " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2)); ++ } ++ return -2; + } -+ -+ /* Priority */ -+ reg_data = TITAN_GE_READ(0x1038 + (port_num << 12)); -+ reg_data &= ~(0x00f00000); -+ TITAN_GE_WRITE((0x1038 + (port_num << 12)), reg_data); -+ -+ /* Step 5: GMII config */ -+ titan_ge_gmii_config(port_num); -+ -+ if (config_done == 0) { -+ TITAN_GE_WRITE(0x1a80, 0); -+ config_done = 1; ++ keyidx >>= 6; ++ if (tkey->key_idx != keyidx) { ++ printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame " ++ "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv); ++ return -6; + } ++ if (!tkey->key_set) { ++ if (net_ratelimit()) { ++ printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT ++ " with keyid=%d that does not have a configured" ++ " key\n", MAC_ARG(hdr->addr2), keyidx); ++ } ++ return -3; ++ } ++ iv16 = (pos[0] << 8) | pos[2]; ++ iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); ++ pos += 8; ++#ifndef JOHN_TKIP ++#if 0 ++ if (iv32 < tkey->rx_iv32 || ++ (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) { ++ if (net_ratelimit()) { ++ printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT ++ " previous TSC %08x%04x received TSC " ++ "%08x%04x\n", MAC_ARG(hdr->addr2), ++ tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); ++ } ++ tkey->dot11RSNAStatsTKIPReplays++; ++ return -4; ++ } ++#endif ++ if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) { ++ tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32); ++ tkey->rx_phase1_done = 1; ++ } ++ tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16); ++ ++ plen = skb->len - hdr_len - 12; ++ #if(LINUX_VERSION_CODE tfm_arc4, rc4key, 16); ++ sg.page = virt_to_page(pos); ++ sg.offset = offset_in_page(pos); ++ sg.length = plen + 4; ++ crypto_cipher_decrypt(tkey->tfm_arc4, &sg, &sg, plen + 4); ++ #else ++ crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); ++ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) ++ sg.page = virt_to_page(pos); ++ sg.offset = offset_in_page(pos); ++ sg.length = plen + 4; ++ #else ++ sg_init_one(&sg, pos, plen + 4); ++ #endif ++ if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { ++ if (net_ratelimit()) { ++ printk(KERN_DEBUG ": TKIP: failed to decrypt " ++ "received packet from " MAC_FMT "\n", ++ MAC_ARG(hdr->addr2)); ++ } ++ return -7; ++ } ++ #endif + -+ return TITAN_OK; -+} -+ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++ crc = ~crc32_le(~0, pos, plen); ++#else ++ crc = ~ether_crc_le(plen, pos); ++#endif ++ icv[0] = crc; ++ icv[1] = crc >> 8; ++ icv[2] = crc >> 16; ++ icv[3] = crc >> 24; ++ if (memcmp(icv, pos + plen, 4) != 0) { ++ if (iv32 != tkey->rx_iv32) { ++ /* Previously cached Phase1 result was already lost, so ++ * it needs to be recalculated for the next packet. */ ++ tkey->rx_phase1_done = 0; ++ } ++ if (net_ratelimit()) { ++ printk(KERN_DEBUG "TKIP: ICV error detected: STA=" ++ MAC_FMT "\n", MAC_ARG(hdr->addr2)); ++ } ++ tkey->dot11RSNAStatsTKIPICVErrors++; ++ return -5; ++ } ++ ++#endif /* JOHN_TKIP */ ++ ++ /* Update real counters only after Michael MIC verification has ++ * completed */ ++ tkey->rx_iv32_new = iv32; ++ tkey->rx_iv16_new = iv16; ++ ++ /* Remove IV and ICV */ ++ memmove(skb->data + 8, skb->data, hdr_len); ++ skb_pull(skb, 8); ++ skb_trim(skb, skb->len - 4); ++ ++//john's test ++#ifdef JOHN_DUMP ++if( ((u16*)skb->data)[0] & 0x4000){ ++ printk("@@ rx decrypted skb->data"); ++ int i; ++ for(i=0;ilen;i++){ ++ if( (i%24)==0 ) printk("\n"); ++ printk("%2x ", ((u8*)skb->data)[i]); ++ } ++ printk("\n"); ++} ++#endif /*JOHN_DUMP*/ ++ return keyidx; ++} ++ ++#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++static int michael_mic(struct ieee80211_tkip_data *tkey, u8 *key, u8 *hdr, ++ u8 *data, size_t data_len, u8 *mic) ++{ ++ struct scatterlist sg[2]; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++ struct hash_desc desc; ++ int ret=0; ++#endif ++ if (tkey->tfm_michael == NULL) { ++ printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); ++ return -1; ++ } ++ sg[0].page = virt_to_page(hdr); ++ sg[0].offset = offset_in_page(hdr); ++ sg[0].length = 16; ++ ++ sg[1].page = virt_to_page(data); ++ sg[1].offset = offset_in_page(data); ++ sg[1].length = data_len; ++ ++ //crypto_digest_init(tkey->tfm_michael); ++ //crypto_digest_setkey(tkey->tfm_michael, key, 8); ++ //crypto_digest_update(tkey->tfm_michael, sg, 2); ++ //crypto_digest_final(tkey->tfm_michael, mic); ++ ++ //return 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ crypto_digest_init(tkey->tfm_michael); ++ crypto_digest_setkey(tkey->tfm_michael, key, 8); ++ crypto_digest_update(tkey->tfm_michael, sg, 2); ++ crypto_digest_final(tkey->tfm_michael, mic); ++ ++ return 0; ++#else ++if (crypto_hash_setkey(tkey->tfm_michael, key, 8)) ++ return -1; ++ ++// return 0; ++ desc.tfm = tkey->tfm_michael; ++ desc.flags = 0; ++ ret = crypto_hash_digest(&desc, sg, data_len + 16, mic); ++ return ret; ++#endif ++} ++#else ++static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr, ++ u8 * data, size_t data_len, u8 * mic) ++{ ++ struct hash_desc desc; ++ struct scatterlist sg[2]; ++ ++ if (tfm_michael == NULL) { ++ printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); ++ return -1; ++ } ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ++ sg[0].page = virt_to_page(hdr); ++ sg[0].offset = offset_in_page(hdr); ++ sg[0].length = 16; ++ ++ sg[1].page = virt_to_page(data); ++ sg[1].offset = offset_in_page(data); ++ sg[1].length = data_len; ++#else ++ sg_init_table(sg, 2); ++ sg_set_buf(&sg[0], hdr, 16); ++ sg_set_buf(&sg[1], data, data_len); ++#endif ++ if (crypto_hash_setkey(tfm_michael, key, 8)) ++ return -1; ++ ++ desc.tfm = tfm_michael; ++ desc.flags = 0; ++ return crypto_hash_digest(&desc, sg, data_len + 16, mic); ++} ++#endif ++ ++ ++ ++static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) ++{ ++ struct ieee80211_hdr *hdr11; ++ ++ hdr11 = (struct ieee80211_hdr *) skb->data; ++ switch (le16_to_cpu(hdr11->frame_ctl) & ++ (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { ++ case IEEE80211_FCTL_TODS: ++ memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ ++ memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ ++ break; ++ case IEEE80211_FCTL_FROMDS: ++ memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ ++ memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */ ++ break; ++ case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: ++ memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ ++ memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */ ++ break; ++ case 0: ++ memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ ++ memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ ++ break; ++ } ++ ++ hdr[12] = 0; /* priority */ ++ ++ hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ ++} ++ ++ ++static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv) ++{ ++ struct ieee80211_tkip_data *tkey = priv; ++ u8 *pos; ++ struct ieee80211_hdr *hdr; ++ ++ hdr = (struct ieee80211_hdr *) skb->data; ++ ++ if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { ++ printk(KERN_DEBUG "Invalid packet for Michael MIC add " ++ "(tailroom=%d hdr_len=%d skb->len=%d)\n", ++ skb_tailroom(skb), hdr_len, skb->len); ++ return -1; ++ } ++ ++ michael_mic_hdr(skb, tkey->tx_hdr); ++ ++ // { david, 2006.9.1 ++ // fix the wpa process with wmm enabled. ++ if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) { ++ tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; ++ } ++ // } ++ pos = skb_put(skb, 8); ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr, ++ skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) ++ #else ++ if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr, ++ skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) ++ #endif ++ return -1; ++ ++ return 0; ++} ++ ++ ++#if WIRELESS_EXT >= 18 ++static void ieee80211_michael_mic_failure(struct net_device *dev, ++ struct ieee80211_hdr *hdr, ++ int keyidx) ++{ ++ union iwreq_data wrqu; ++ struct iw_michaelmicfailure ev; ++ ++ /* TODO: needed parameters: count, keyid, key type, TSC */ ++ memset(&ev, 0, sizeof(ev)); ++ ev.flags = keyidx & IW_MICFAILURE_KEY_ID; ++ if (hdr->addr1[0] & 0x01) ++ ev.flags |= IW_MICFAILURE_GROUP; ++ else ++ ev.flags |= IW_MICFAILURE_PAIRWISE; ++ ev.src_addr.sa_family = ARPHRD_ETHER; ++ memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN); ++ memset(&wrqu, 0, sizeof(wrqu)); ++ wrqu.data.length = sizeof(ev); ++ wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev); ++} ++#elif WIRELESS_EXT >= 15 ++static void ieee80211_michael_mic_failure(struct net_device *dev, ++ struct ieee80211_hdr *hdr, ++ int keyidx) ++{ ++ union iwreq_data wrqu; ++ char buf[128]; ++ ++ /* TODO: needed parameters: count, keyid, key type, TSC */ ++ sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=" ++ MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni", ++ MAC_ARG(hdr->addr2)); ++ memset(&wrqu, 0, sizeof(wrqu)); ++ wrqu.data.length = strlen(buf); ++ wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); ++} ++#else /* WIRELESS_EXT >= 15 */ ++static inline void ieee80211_michael_mic_failure(struct net_device *dev, ++ struct ieee80211_hdr *hdr, ++ int keyidx) ++{ ++} ++#endif /* WIRELESS_EXT >= 15 */ ++ ++ ++static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, ++ int hdr_len, void *priv) ++{ ++ struct ieee80211_tkip_data *tkey = priv; ++ u8 mic[8]; ++ struct ieee80211_hdr *hdr; ++ ++ hdr = (struct ieee80211_hdr *) skb->data; ++ ++ if (!tkey->key_set) ++ return -1; ++ ++ michael_mic_hdr(skb, tkey->rx_hdr); ++ // { david, 2006.9.1 ++ // fix the wpa process with wmm enabled. ++ if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) { ++ tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; ++ } ++ // } ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr, ++ skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) ++ #else ++ if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr, ++ skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) ++ #endif ++ return -1; ++ if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { ++ struct ieee80211_hdr *hdr; ++ hdr = (struct ieee80211_hdr *) skb->data; ++ printk(KERN_DEBUG "%s: Michael MIC verification failed for " ++ "MSDU from " MAC_FMT " keyidx=%d\n", ++ skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2), ++ keyidx); ++ if (skb->dev) ++ ieee80211_michael_mic_failure(skb->dev, hdr, keyidx); ++ tkey->dot11RSNAStatsTKIPLocalMICFailures++; ++ return -1; ++ } ++ ++ /* Update TSC counters for RX now that the packet verification has ++ * completed. */ ++ tkey->rx_iv32 = tkey->rx_iv32_new; ++ tkey->rx_iv16 = tkey->rx_iv16_new; ++ ++ skb_trim(skb, skb->len - 8); ++ ++ return 0; ++} ++ ++ ++static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv) ++{ ++ struct ieee80211_tkip_data *tkey = priv; ++ int keyidx; ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ struct crypto_tfm *tfm = tkey->tfm_michael; ++ struct crypto_tfm *tfm2 = tkey->tfm_arc4; ++ #else ++ struct crypto_hash *tfm = tkey->tx_tfm_michael; ++ struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4; ++ struct crypto_hash *tfm3 = tkey->rx_tfm_michael; ++ struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4; ++ #endif ++ ++ keyidx = tkey->key_idx; ++ memset(tkey, 0, sizeof(*tkey)); ++ tkey->key_idx = keyidx; ++ ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ tkey->tfm_michael = tfm; ++ tkey->tfm_arc4 = tfm2; ++ #else ++ tkey->tx_tfm_michael = tfm; ++ tkey->tx_tfm_arc4 = tfm2; ++ tkey->rx_tfm_michael = tfm3; ++ tkey->rx_tfm_arc4 = tfm4; ++ #endif ++ ++ if (len == TKIP_KEY_LEN) { ++ memcpy(tkey->key, key, TKIP_KEY_LEN); ++ tkey->key_set = 1; ++ tkey->tx_iv16 = 1; /* TSC is initialized to 1 */ ++ if (seq) { ++ tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) | ++ (seq[3] << 8) | seq[2]; ++ tkey->rx_iv16 = (seq[1] << 8) | seq[0]; ++ } ++ } else if (len == 0) ++ tkey->key_set = 0; ++ else ++ return -1; ++ ++ return 0; ++} ++ ++ ++static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv) ++{ ++ struct ieee80211_tkip_data *tkey = priv; ++ ++ if (len < TKIP_KEY_LEN) ++ return -1; ++ ++ if (!tkey->key_set) ++ return 0; ++ memcpy(key, tkey->key, TKIP_KEY_LEN); ++ ++ if (seq) { ++ /* Return the sequence number of the last transmitted frame. */ ++ u16 iv16 = tkey->tx_iv16; ++ u32 iv32 = tkey->tx_iv32; ++ if (iv16 == 0) ++ iv32--; ++ iv16--; ++ seq[0] = tkey->tx_iv16; ++ seq[1] = tkey->tx_iv16 >> 8; ++ seq[2] = tkey->tx_iv32; ++ seq[3] = tkey->tx_iv32 >> 8; ++ seq[4] = tkey->tx_iv32 >> 16; ++ seq[5] = tkey->tx_iv32 >> 24; ++ } ++ ++ return TKIP_KEY_LEN; ++} ++ ++ ++static char * ieee80211_tkip_print_stats(char *p, void *priv) ++{ ++ struct ieee80211_tkip_data *tkip = priv; ++ p += sprintf(p, "key[%d] alg=TKIP key_set=%d " ++ "tx_pn=%02x%02x%02x%02x%02x%02x " ++ "rx_pn=%02x%02x%02x%02x%02x%02x " ++ "replays=%d icv_errors=%d local_mic_failures=%d\n", ++ tkip->key_idx, tkip->key_set, ++ (tkip->tx_iv32 >> 24) & 0xff, ++ (tkip->tx_iv32 >> 16) & 0xff, ++ (tkip->tx_iv32 >> 8) & 0xff, ++ tkip->tx_iv32 & 0xff, ++ (tkip->tx_iv16 >> 8) & 0xff, ++ tkip->tx_iv16 & 0xff, ++ (tkip->rx_iv32 >> 24) & 0xff, ++ (tkip->rx_iv32 >> 16) & 0xff, ++ (tkip->rx_iv32 >> 8) & 0xff, ++ tkip->rx_iv32 & 0xff, ++ (tkip->rx_iv16 >> 8) & 0xff, ++ tkip->rx_iv16 & 0xff, ++ tkip->dot11RSNAStatsTKIPReplays, ++ tkip->dot11RSNAStatsTKIPICVErrors, ++ tkip->dot11RSNAStatsTKIPLocalMICFailures); ++ return p; ++} ++ ++ ++static struct ieee80211_crypto_ops ieee80211_crypt_tkip = { ++ .name = "TKIP", ++ .init = ieee80211_tkip_init, ++ .deinit = ieee80211_tkip_deinit, ++ .encrypt_mpdu = ieee80211_tkip_encrypt, ++ .decrypt_mpdu = ieee80211_tkip_decrypt, ++ .encrypt_msdu = ieee80211_michael_mic_add, ++ .decrypt_msdu = ieee80211_michael_mic_verify, ++ .set_key = ieee80211_tkip_set_key, ++ .get_key = ieee80211_tkip_get_key, ++ .print_stats = ieee80211_tkip_print_stats, ++ .extra_prefix_len = 4 + 4, /* IV + ExtIV */ ++ .extra_postfix_len = 8 + 4, /* MIC + ICV */ ++ .owner = THIS_MODULE, ++}; ++ ++ ++int __init ieee80211_crypto_tkip_init(void) ++{ ++ return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip); ++} ++ ++ ++void __exit ieee80211_crypto_tkip_exit(void) ++{ ++ ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip); ++} ++ ++ ++void ieee80211_tkip_null(void) ++{ ++// printk("============>%s()\n", __FUNCTION__); ++ return; ++} ++ ++#if 0 ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++EXPORT_SYMBOL(ieee80211_tkip_null); ++#else ++EXPORT_SYMBOL_NOVERS(ieee80211_tkip_null); ++#endif ++ ++ ++module_init(ieee80211_crypto_tkip_init); ++module_exit(ieee80211_crypto_tkip_exit); ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt_wep.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt_wep.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt_wep.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_crypt_wep.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,383 @@ ++/* ++ * Host AP crypt: host-based WEP encryption implementation for Host AP driver ++ * ++ * Copyright (c) 2002-2004, Jouni Malinen ++ * ++ * 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. See README and COPYING for ++ * more details. ++ */ ++ ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ieee80211.h" ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) ++#include "rtl_crypto.h" ++#else ++#include ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ #include ++#else ++ #include ++#endif ++//#include ++#include ++ ++MODULE_AUTHOR("Jouni Malinen"); ++MODULE_DESCRIPTION("Host AP crypt: WEP"); ++MODULE_LICENSE("GPL"); ++ ++ ++struct prism2_wep_data { ++ u32 iv; ++#define WEP_KEY_LEN 13 ++ u8 key[WEP_KEY_LEN + 1]; ++ u8 key_len; ++ u8 key_idx; ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ struct crypto_tfm *tfm; ++ #else ++ struct crypto_blkcipher *tx_tfm; ++ struct crypto_blkcipher *rx_tfm; ++ #endif ++}; ++ ++ ++static void * prism2_wep_init(int keyidx) ++{ ++ struct prism2_wep_data *priv; ++ ++ priv = kmalloc(sizeof(*priv), GFP_ATOMIC); ++ if (priv == NULL) ++ goto fail; ++ memset(priv, 0, sizeof(*priv)); ++ priv->key_idx = keyidx; ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ priv->tfm = crypto_alloc_tfm("arc4", 0); ++ if (priv->tfm == NULL) { ++ printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " ++ "crypto API arc4\n"); ++ goto fail; ++ } ++ #else ++ priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(priv->tx_tfm)) { ++ printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " ++ "crypto API arc4\n"); ++ priv->tx_tfm = NULL; ++ goto fail; ++ } ++ priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(priv->rx_tfm)) { ++ printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " ++ "crypto API arc4\n"); ++ priv->rx_tfm = NULL; ++ goto fail; ++ } ++ #endif ++ ++ /* start WEP IV from a random value */ ++ get_random_bytes(&priv->iv, 4); ++ ++ return priv; ++ ++fail: ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ if (priv) { ++ if (priv->tfm) ++ crypto_free_tfm(priv->tfm); ++ kfree(priv); ++ } ++ #else ++ if (priv) { ++ if (priv->tx_tfm) ++ crypto_free_blkcipher(priv->tx_tfm); ++ if (priv->rx_tfm) ++ crypto_free_blkcipher(priv->rx_tfm); ++ kfree(priv); ++ } ++ #endif ++ return NULL; ++} ++ ++ ++static void prism2_wep_deinit(void *priv) ++{ ++ struct prism2_wep_data *_priv = priv; ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ if (_priv && _priv->tfm) ++ crypto_free_tfm(_priv->tfm); ++ #else ++ if (_priv) { ++ if (_priv->tx_tfm) ++ crypto_free_blkcipher(_priv->tx_tfm); ++ if (_priv->rx_tfm) ++ crypto_free_blkcipher(_priv->rx_tfm); ++ } ++ #endif ++ kfree(priv); ++} ++ ++ ++/* Perform WEP encryption on given skb that has at least 4 bytes of headroom ++ * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted, ++ * so the payload length increases with 8 bytes. ++ * ++ * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) ++ */ ++static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) ++{ ++ struct prism2_wep_data *wep = priv; ++#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) ++ struct blkcipher_desc desc = {.tfm = wep->tx_tfm}; ++#endif ++ u32 klen, len; ++ u8 key[WEP_KEY_LEN + 3]; ++ u8 *pos; ++#ifndef JOHN_HWSEC ++ u32 crc; ++ u8 *icv; ++ struct scatterlist sg; ++#endif ++ if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 || ++ skb->len < hdr_len) ++ return -1; ++ ++ len = skb->len - hdr_len; ++ pos = skb_push(skb, 4); ++ memmove(pos, pos + 4, hdr_len); ++ pos += hdr_len; ++ ++ klen = 3 + wep->key_len; ++ ++ wep->iv++; ++ ++ /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key ++ * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N) ++ * can be used to speedup attacks, so avoid using them. */ ++ if ((wep->iv & 0xff00) == 0xff00) { ++ u8 B = (wep->iv >> 16) & 0xff; ++ if (B >= 3 && B < klen) ++ wep->iv += 0x0100; ++ } ++ ++ /* Prepend 24-bit IV to RC4 key and TX frame */ ++ *pos++ = key[0] = (wep->iv >> 16) & 0xff; ++ *pos++ = key[1] = (wep->iv >> 8) & 0xff; ++ *pos++ = key[2] = wep->iv & 0xff; ++ *pos++ = wep->key_idx << 6; ++ ++ /* Copy rest of the WEP key (the secret part) */ ++ memcpy(key + 3, wep->key, wep->key_len); ++ ++#ifndef JOHN_HWSEC ++ /* Append little-endian CRC32 and encrypt it to produce ICV */ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++ crc = ~crc32_le(~0, pos, len); ++#else ++ crc = ~ether_crc_le(len, pos); ++#endif ++ icv = skb_put(skb, 4); ++ icv[0] = crc; ++ icv[1] = crc >> 8; ++ icv[2] = crc >> 16; ++ icv[3] = crc >> 24; ++ ++ #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ crypto_cipher_setkey(wep->tfm, key, klen); ++ sg.page = virt_to_page(pos); ++ sg.offset = offset_in_page(pos); ++ sg.length = len + 4; ++ crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4); ++ ++ return 0; ++ #else ++ crypto_blkcipher_setkey(wep->tx_tfm, key, klen); ++ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) ++ sg.page = virt_to_page(pos); ++ sg.offset = offset_in_page(pos); ++ sg.length = len + 4; ++ #else ++ sg_init_one(&sg, pos, len + 4); ++ #endif ++ return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); ++ #endif ++#endif /* JOHN_HWSEC */ ++ return 0; ++} ++ ++ ++/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of ++ * the frame: IV (4 bytes), encrypted payload (including SNAP header), ++ * ICV (4 bytes). len includes both IV and ICV. ++ * ++ * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on ++ * failure. If frame is OK, IV and ICV will be removed. ++ */ ++static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) ++{ ++ struct prism2_wep_data *wep = priv; ++ #if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) ++ struct blkcipher_desc desc = {.tfm = wep->rx_tfm}; ++ #endif ++ u32 klen, plen; ++ u8 key[WEP_KEY_LEN + 3]; ++ u8 keyidx, *pos; ++#ifndef JOHN_HWSEC ++ u32 crc; ++ u8 icv[4]; ++ struct scatterlist sg; ++#endif ++ if (skb->len < hdr_len + 8) ++ return -1; ++ ++ pos = skb->data + hdr_len; ++ key[0] = *pos++; ++ key[1] = *pos++; ++ key[2] = *pos++; ++ keyidx = *pos++ >> 6; ++ if (keyidx != wep->key_idx) ++ return -1; ++ ++ klen = 3 + wep->key_len; ++ ++ /* Copy rest of the WEP key (the secret part) */ ++ memcpy(key + 3, wep->key, wep->key_len); ++ ++ /* Apply RC4 to data and compute CRC32 over decrypted data */ ++ plen = skb->len - hdr_len - 8; ++#ifndef JOHN_HWSEC ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) ++ crypto_cipher_setkey(wep->tfm, key, klen); ++ sg.page = virt_to_page(pos); ++ sg.offset = offset_in_page(pos); ++ sg.length = plen + 4; ++ crypto_cipher_decrypt(wep->tfm, &sg, &sg, plen + 4); ++#else ++ crypto_blkcipher_setkey(wep->rx_tfm, key, klen); ++ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) ++ sg.page = virt_to_page(pos); ++ sg.offset = offset_in_page(pos); ++ sg.length = plen + 4; ++ #else ++ sg_init_one(&sg, pos, plen + 4); ++ #endif ++ if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) ++ return -7; ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++ crc = ~crc32_le(~0, pos, plen); ++#else ++ crc = ~ether_crc_le(plen, pos); ++#endif ++ icv[0] = crc; ++ icv[1] = crc >> 8; ++ icv[2] = crc >> 16; ++ icv[3] = crc >> 24; ++ ++ if (memcmp(icv, pos + plen, 4) != 0) { ++ /* ICV mismatch - drop frame */ ++ return -2; ++ } ++#endif /* JOHN_HWSEC */ ++ ++ /* Remove IV and ICV */ ++ memmove(skb->data + 4, skb->data, hdr_len); ++ skb_pull(skb, 4); ++ skb_trim(skb, skb->len - 4); ++ return 0; ++} ++ ++ ++static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv) ++{ ++ struct prism2_wep_data *wep = priv; ++ ++ if (len < 0 || len > WEP_KEY_LEN) ++ return -1; ++ ++ memcpy(wep->key, key, len); ++ wep->key_len = len; ++ ++ return 0; ++} ++ ++ ++static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv) ++{ ++ struct prism2_wep_data *wep = priv; ++ ++ if (len < wep->key_len) ++ return -1; ++ ++ memcpy(key, wep->key, wep->key_len); ++ ++ return wep->key_len; ++} ++ ++ ++static char * prism2_wep_print_stats(char *p, void *priv) ++{ ++ struct prism2_wep_data *wep = priv; ++ p += sprintf(p, "key[%d] alg=WEP len=%d\n", ++ wep->key_idx, wep->key_len); ++ return p; ++} ++ ++ ++static struct ieee80211_crypto_ops ieee80211_crypt_wep = { ++ .name = "WEP", ++ .init = prism2_wep_init, ++ .deinit = prism2_wep_deinit, ++ .encrypt_mpdu = prism2_wep_encrypt, ++ .decrypt_mpdu = prism2_wep_decrypt, ++ .encrypt_msdu = NULL, ++ .decrypt_msdu = NULL, ++ .set_key = prism2_wep_set_key, ++ .get_key = prism2_wep_get_key, ++ .print_stats = prism2_wep_print_stats, ++ .extra_prefix_len = 4, /* IV */ ++ .extra_postfix_len = 4, /* ICV */ ++ .owner = THIS_MODULE, ++}; ++ ++ ++int __init ieee80211_crypto_wep_init(void) ++{ ++ return ieee80211_register_crypto_ops(&ieee80211_crypt_wep); ++} ++ ++ ++void __exit ieee80211_crypto_wep_exit(void) ++{ ++ ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep); ++} ++ ++ ++void ieee80211_wep_null(void) ++{ ++// printk("============>%s()\n", __FUNCTION__); ++ return; ++} ++#if 0 ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++EXPORT_SYMBOL(ieee80211_wep_null); ++#else ++EXPORT_SYMBOL_NOVERS(ieee80211_wep_null); ++#endif ++ ++module_init(ieee80211_crypto_wep_init); ++module_exit(ieee80211_crypto_wep_exit); ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,1913 @@ ++/* ++ * Merged with mainline ieee80211.h in Aug 2004. Original ieee802_11 ++ * remains copyright by the original authors ++ * ++ * Portions of the merged code are based on Host AP (software wireless ++ * LAN access point) driver for Intersil Prism2/2.5/3. ++ * ++ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen ++ * ++ * Copyright (c) 2002-2003, Jouni Malinen ++ * ++ * Adaption to a generic IEEE 802.11 stack by James Ketrenos ++ * ++ * Copyright (c) 2004, Intel Corporation ++ * ++ * Modified for Realtek's wi-fi cards by Andrea Merello ++ * ++ * ++ * 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. See README and COPYING for ++ * more details. ++ */ ++#ifndef IEEE80211_H ++#define IEEE80211_H ++#include /* ETH_ALEN */ ++#include /* ARRAY_SIZE */ ++#include ++#include ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++#include ++#else ++#include ++#include ++#endif ++#include ++#include ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)) ++#include ++#endif ++/* ++#ifndef bool ++#define bool int ++#endif ++ ++#ifndef true ++#define true 1 ++#endif ++ ++#ifndef false ++#define false 0 ++#endif ++*/ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) ++#ifndef bool ++typedef enum{false = 0, true} bool; ++#endif ++#endif ++//#ifdef JOHN_HWSEC ++#define KEY_TYPE_NA 0x0 ++#define KEY_TYPE_WEP40 0x1 ++#define KEY_TYPE_TKIP 0x2 ++#define KEY_TYPE_CCMP 0x4 ++#define KEY_TYPE_WEP104 0x5 ++//#endif ++ ++ ++#define aSifsTime 10 ++ ++#define MGMT_QUEUE_NUM 5 ++ ++ ++#define IEEE_CMD_SET_WPA_PARAM 1 ++#define IEEE_CMD_SET_WPA_IE 2 ++#define IEEE_CMD_SET_ENCRYPTION 3 ++#define IEEE_CMD_MLME 4 ++ ++#define IEEE_PARAM_WPA_ENABLED 1 ++#define IEEE_PARAM_TKIP_COUNTERMEASURES 2 ++#define IEEE_PARAM_DROP_UNENCRYPTED 3 ++#define IEEE_PARAM_PRIVACY_INVOKED 4 ++#define IEEE_PARAM_AUTH_ALGS 5 ++#define IEEE_PARAM_IEEE_802_1X 6 ++//It should consistent with the driver_XXX.c ++// David, 2006.9.26 ++#define IEEE_PARAM_WPAX_SELECT 7 ++//Added for notify the encryption type selection ++// David, 2006.9.26 ++#define IEEE_PROTO_WPA 1 ++#define IEEE_PROTO_RSN 2 ++//Added for notify the encryption type selection ++// David, 2006.9.26 ++#define IEEE_WPAX_USEGROUP 0 ++#define IEEE_WPAX_WEP40 1 ++#define IEEE_WPAX_TKIP 2 ++#define IEEE_WPAX_WRAP 3 ++#define IEEE_WPAX_CCMP 4 ++#define IEEE_WPAX_WEP104 5 ++ ++#define IEEE_KEY_MGMT_IEEE8021X 1 ++#define IEEE_KEY_MGMT_PSK 2 ++ ++ ++ ++#define IEEE_MLME_STA_DEAUTH 1 ++#define IEEE_MLME_STA_DISASSOC 2 ++ ++ ++#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2 ++#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3 ++#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4 ++#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5 ++#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6 ++#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7 ++ ++ ++#define IEEE_CRYPT_ALG_NAME_LEN 16 ++ ++//#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)) ++#define ieee80211_wx_get_scan ieee80211_wx_get_scan_rtl ++#define ieee80211_wx_set_encode ieee80211_wx_set_encode_rtl ++#define ieee80211_wx_get_encode ieee80211_wx_get_encode_rtl ++//////////////////////////////// ++// added for kernel conflict under FC5 ++#define ieee80211_wx_get_name ieee80211_wx_get_name_rtl ++#define free_ieee80211 free_ieee80211_rtl ++#define alloc_ieee80211 alloc_ieee80211_rtl ++/////////////////////////////// ++//#endif ++#define ieee80211_rx ieee80211_rx_rtl ++#define ieee80211_wake_queue ieee80211_wake_queue_rtl ++#define ieee80211_stop_queue ieee80211_stop_queue_rtl ++#define ieee80211_wx_set_auth ieee80211_wx_set_auth_rtl ++#define ieee80211_get_crypto_ops ieee80211_get_crypto_ops_rtl ++#define ieee80211_crypt_delayed_deinit ieee80211_crypt_delayed_deinit_rtl ++ ++#define ieee80211_start_scan ieee80211_start_scan_rtl ++#define ieee80211_register_crypto_ops ieee80211_register_crypto_ops_rtl ++#define ieee80211_unregister_crypto_ops ieee80211_unregister_crypto_ops_rtl ++#define ieee80211_crypt_deinit_entries ieee80211_crypt_deinit_entries_rtl ++#define ieee80211_crypt_deinit_handler ieee80211_crypt_deinit_handler_rtl ++typedef struct ieee_param { ++ u32 cmd; ++ u8 sta_addr[ETH_ALEN]; ++ union { ++ struct { ++ u8 name; ++ u32 value; ++ } wpa_param; ++ struct { ++ u32 len; ++ u8 reserved[32]; ++ u8 data[0]; ++ } wpa_ie; ++ struct{ ++ int command; ++ int reason_code; ++ } mlme; ++ struct { ++ u8 alg[IEEE_CRYPT_ALG_NAME_LEN]; ++ u8 set_tx; ++ u32 err; ++ u8 idx; ++ u8 seq[8]; /* sequence counter (set: RX, get: TX) */ ++ u16 key_len; ++ u8 key[0]; ++ } crypt; ++ ++ } u; ++}ieee_param; ++ ++ ++#if WIRELESS_EXT < 17 ++#define IW_QUAL_QUAL_INVALID 0x10 ++#define IW_QUAL_LEVEL_INVALID 0x20 ++#define IW_QUAL_NOISE_INVALID 0x40 ++#define IW_QUAL_QUAL_UPDATED 0x1 ++#define IW_QUAL_LEVEL_UPDATED 0x2 ++#define IW_QUAL_NOISE_UPDATED 0x4 ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) ++static inline void tq_init(struct tq_struct * task, void(*func)(void *), void *data) ++{ ++ task->routine = func; ++ task->data = data; ++ //task->next = NULL; ++ INIT_LIST_HEAD(&task->list); ++ task->sync = 0; ++} ++#endif ++ ++// linux under 2.6.9 release may not support it, so modify it for common use ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)) ++//#define MSECS(t) (1000 * ((t) / HZ) + 1000 * ((t) % HZ) / HZ) ++#define MSECS(t) (HZ * ((t) / 1000) + (HZ * ((t) % 1000)) / 1000) ++static inline unsigned long msleep_interruptible_rtl(unsigned int msecs) ++{ ++ unsigned long timeout = MSECS(msecs) + 1; ++ ++ while (timeout) { ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ timeout = schedule_timeout(timeout); ++ } ++ return timeout; ++} ++#else ++#define MSECS(t) msecs_to_jiffies(t) ++#define msleep_interruptible_rtl msleep_interruptible ++#endif ++ ++#define IEEE80211_DATA_LEN 2304 ++/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section ++ 6.2.1.1.2. ++ ++ The figure in section 7.1.2 suggests a body size of up to 2312 ++ 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 IEEE80211_HLEN 30 ++#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) ++ ++/* this is stolen and modified from the madwifi driver*/ ++#define IEEE80211_FC0_TYPE_MASK 0x0c ++#define IEEE80211_FC0_TYPE_DATA 0x08 ++#define IEEE80211_FC0_SUBTYPE_MASK 0xB0 ++#define IEEE80211_FC0_SUBTYPE_QOS 0x80 ++ ++#define IEEE80211_QOS_HAS_SEQ(fc) \ ++ (((fc) & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == \ ++ (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) ++ ++/* this is stolen from ipw2200 driver */ ++#define IEEE_IBSS_MAC_HASH_SIZE 31 ++#define IEEE_MESH_MAC_HASH_SIZE 31 ++struct ieee_ibss_seq { ++ u8 mac[ETH_ALEN]; ++ u16 seq_num[17]; ++ u16 frag_num[17]; ++ unsigned long packet_time[17]; ++ struct list_head list; ++}; ++ ++struct ieee_mesh_seq { ++ u8 mac[ETH_ALEN]; ++ u16 seq_num; ++ u16 frag_num; ++ unsigned long packet_time; ++ struct list_head list; ++}; ++ ++struct ieee80211_hdr { ++ u16 frame_ctl; ++ u16 duration_id; ++ u8 addr1[ETH_ALEN]; ++ u8 addr2[ETH_ALEN]; ++ u8 addr3[ETH_ALEN]; ++ u16 seq_ctl; ++ u8 addr4[ETH_ALEN]; ++} __attribute__ ((packed)); ++ ++struct ieee80211_hdr_QOS { ++ u16 frame_ctl; ++ u16 duration_id; ++ u8 addr1[ETH_ALEN]; ++ u8 addr2[ETH_ALEN]; ++ u8 addr3[ETH_ALEN]; ++ u16 seq_ctl; ++ u8 addr4[ETH_ALEN]; ++ u16 QOS_ctl; ++} __attribute__ ((packed)); ++ ++struct ieee80211_hdr_3addr { ++ u16 frame_ctl; ++ u16 duration_id; ++ u8 addr1[ETH_ALEN]; ++ u8 addr2[ETH_ALEN]; ++ u8 addr3[ETH_ALEN]; ++ u16 seq_ctl; ++} __attribute__ ((packed)); ++ ++struct ieee80211_hdr_3addr_QOS { ++ u16 frame_ctl; ++ u16 duration_id; ++ u8 addr1[ETH_ALEN]; ++ u8 addr2[ETH_ALEN]; ++ u8 addr3[ETH_ALEN]; ++ u16 seq_ctl; ++ u16 QOS_ctl; ++} __attribute__ ((packed)); ++ ++enum eap_type { ++ EAP_PACKET = 0, ++ EAPOL_START, ++ EAPOL_LOGOFF, ++ EAPOL_KEY, ++ EAPOL_ENCAP_ASF_ALERT ++}; ++ ++//by lizhaoming for LED 2008.6.23 from r8187_led.h ++#ifdef LED ++typedef enum _LED_CTL_MODE { ++ LED_CTL_POWER_ON, ++ LED_CTL_POWER_OFF, ++ LED_CTL_LINK, ++ LED_CTL_NO_LINK, ++ LED_CTL_TX, ++ LED_CTL_RX, ++ LED_CTL_SITE_SURVEY, ++} LED_CTL_MODE; ++#endif ++ ++static const char *eap_types[] = { ++ [EAP_PACKET] = "EAP-Packet", ++ [EAPOL_START] = "EAPOL-Start", ++ [EAPOL_LOGOFF] = "EAPOL-Logoff", ++ [EAPOL_KEY] = "EAPOL-Key", ++ [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert" ++}; ++ ++static inline const char *eap_get_type(int type) ++{ ++ return (type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type]; ++} ++ ++struct eapol { ++ u8 snap[6]; ++ u16 ethertype; ++ u8 version; ++ u8 type; ++ u16 length; ++} __attribute__ ((packed)); ++ ++#define IEEE80211_3ADDR_LEN 24 ++#define IEEE80211_4ADDR_LEN 30 ++#define IEEE80211_FCS_LEN 4 ++ ++#define MIN_FRAG_THRESHOLD 256U ++#define MAX_FRAG_THRESHOLD 2346U ++ ++/* Frame control field constants */ ++#define IEEE80211_FCTL_VERS 0x0002 ++#define IEEE80211_FCTL_FTYPE 0x000c ++#define IEEE80211_FCTL_STYPE 0x00f0 ++#define IEEE80211_FCTL_TODS 0x0100 ++#define IEEE80211_FCTL_FROMDS 0x0200 ++#define IEEE80211_FCTL_DSTODS 0x0300 //added by david ++#define IEEE80211_FCTL_MOREFRAGS 0x0400 ++#define IEEE80211_FCTL_RETRY 0x0800 ++#define IEEE80211_FCTL_PM 0x1000 ++#define IEEE80211_FCTL_MOREDATA 0x2000 ++#define IEEE80211_FCTL_WEP 0x4000 ++#define IEEE80211_FCTL_ORDER 0x8000 ++ ++#define IEEE80211_FTYPE_MGMT 0x0000 ++#define IEEE80211_FTYPE_CTL 0x0004 ++#define IEEE80211_FTYPE_DATA 0x0008 ++ ++/* management */ ++#define IEEE80211_STYPE_ASSOC_REQ 0x0000 ++#define IEEE80211_STYPE_ASSOC_RESP 0x0010 ++#define IEEE80211_STYPE_REASSOC_REQ 0x0020 ++#define IEEE80211_STYPE_REASSOC_RESP 0x0030 ++#define IEEE80211_STYPE_PROBE_REQ 0x0040 ++#define IEEE80211_STYPE_PROBE_RESP 0x0050 ++#define IEEE80211_STYPE_BEACON 0x0080 ++#define IEEE80211_STYPE_ATIM 0x0090 ++#define IEEE80211_STYPE_DISASSOC 0x00A0 ++#define IEEE80211_STYPE_AUTH 0x00B0 ++#define IEEE80211_STYPE_DEAUTH 0x00C0 ++#define IEEE80211_STYPE_MANAGE_ACT 0x00D0 ++ ++/* control */ ++#define IEEE80211_STYPE_PSPOLL 0x00A0 ++#define IEEE80211_STYPE_RTS 0x00B0 ++#define IEEE80211_STYPE_CTS 0x00C0 ++#define IEEE80211_STYPE_ACK 0x00D0 ++#define IEEE80211_STYPE_CFEND 0x00E0 ++#define IEEE80211_STYPE_CFENDACK 0x00F0 ++ ++/* data */ ++#define IEEE80211_STYPE_DATA 0x0000 ++#define IEEE80211_STYPE_DATA_CFACK 0x0010 ++#define IEEE80211_STYPE_DATA_CFPOLL 0x0020 ++#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 ++#define IEEE80211_STYPE_NULLFUNC 0x0040 ++#define IEEE80211_STYPE_CFACK 0x0050 ++#define IEEE80211_STYPE_CFPOLL 0x0060 ++#define IEEE80211_STYPE_CFACKPOLL 0x0070 ++#define IEEE80211_STYPE_QOS_DATA 0x0080 //added for WMM 2006/8/2 ++#define IEEE80211_STYPE_QOS_NULL 0x00C0 ++ ++ ++#define IEEE80211_SCTL_FRAG 0x000F ++#define IEEE80211_SCTL_SEQ 0xFFF0 ++ ++ ++/* debug macros */ ++ ++#ifdef CONFIG_IEEE80211_DEBUG ++extern u32 ieee80211_debug_level; ++#define IEEE80211_DEBUG(level, fmt, args...) \ ++do { if (ieee80211_debug_level & (level)) \ ++ printk(KERN_DEBUG "ieee80211: %c %s " fmt, \ ++ in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) ++#else ++#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0) ++#endif /* CONFIG_IEEE80211_DEBUG */ ++ ++/* ++ * To use the debug system; ++ * ++ * If you are defining a new debug classification, simply add it to the #define ++ * list here in the form of: ++ * ++ * #define IEEE80211_DL_xxxx VALUE ++ * ++ * shifting value to the left one bit from the previous entry. xxxx should be ++ * the name of the classification (for example, WEP) ++ * ++ * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your ++ * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want ++ * to send output to that classification. ++ * ++ * To add your debug level to the list of levels seen when you perform ++ * ++ * % cat /proc/net/ipw/debug_level ++ * ++ * you simply need to add your entry to the ipw_debug_levels array. ++ * ++ * If you do not see debug_level in /proc/net/ipw then you do not have ++ * CONFIG_IEEE80211_DEBUG defined in your kernel configuration ++ * ++ */ ++ ++#define IEEE80211_DL_INFO (1<<0) ++#define IEEE80211_DL_WX (1<<1) ++#define IEEE80211_DL_SCAN (1<<2) ++#define IEEE80211_DL_STATE (1<<3) ++#define IEEE80211_DL_MGMT (1<<4) ++#define IEEE80211_DL_FRAG (1<<5) ++#define IEEE80211_DL_EAP (1<<6) ++#define IEEE80211_DL_DROP (1<<7) ++ ++#define IEEE80211_DL_TX (1<<8) ++#define IEEE80211_DL_RX (1<<9) ++ ++#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a) ++#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a) ++#define IEEE80211_DEBUG_INFO(f, a...) IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a) ++ ++#define IEEE80211_DEBUG_WX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a) ++#define IEEE80211_DEBUG_SCAN(f, a...) IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a) ++#define IEEE80211_DEBUG_STATE(f, a...) IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a) ++#define IEEE80211_DEBUG_MGMT(f, a...) IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a) ++#define IEEE80211_DEBUG_FRAG(f, a...) IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a) ++#define IEEE80211_DEBUG_EAP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a) ++#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a) ++#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a) ++#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a) ++#include ++#include ++#include /* ARPHRD_ETHER */ ++ ++#ifndef WIRELESS_SPY ++#define WIRELESS_SPY // enable iwspy support ++#endif ++#include // new driver API ++ ++#ifndef ETH_P_PAE ++#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ ++#endif /* ETH_P_PAE */ ++ ++#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ ++ ++#ifndef ETH_P_80211_RAW ++#define ETH_P_80211_RAW (ETH_P_ECONET + 1) ++#endif ++ ++/* IEEE 802.11 defines */ ++ ++#define P80211_OUI_LEN 3 ++ ++struct ieee80211_snap_hdr { ++ ++ u8 dsap; /* always 0xAA */ ++ u8 ssap; /* always 0xAA */ ++ u8 ctrl; /* always 0x03 */ ++ u8 oui[P80211_OUI_LEN]; /* organizational universal id */ ++ ++} __attribute__ ((packed)); ++ ++#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) ++ ++#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE) ++#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE) ++ ++#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG) ++#define WLAN_GET_SEQ_SEQ(seq) ((seq) & IEEE80211_SCTL_SEQ) ++ ++/* Authentication algorithms */ ++#define WLAN_AUTH_OPEN 0 ++#define WLAN_AUTH_SHARED_KEY 1 ++ ++#define WLAN_AUTH_CHALLENGE_LEN 128 ++ ++#define WLAN_CAPABILITY_BSS (1<<0) ++#define WLAN_CAPABILITY_IBSS (1<<1) ++#define WLAN_CAPABILITY_CF_POLLABLE (1<<2) ++#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) ++#define WLAN_CAPABILITY_PRIVACY (1<<4) ++#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) ++#define WLAN_CAPABILITY_PBCC (1<<6) ++#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) ++#define WLAN_CAPABILITY_SHORT_SLOT (1<<10) ++ ++/* Status codes */ ++#define WLAN_STATUS_SUCCESS 0 ++#define WLAN_STATUS_UNSPECIFIED_FAILURE 1 ++#define WLAN_STATUS_CAPS_UNSUPPORTED 10 ++#define WLAN_STATUS_REASSOC_NO_ASSOC 11 ++#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12 ++#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13 ++#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14 ++#define WLAN_STATUS_CHALLENGE_FAIL 15 ++#define WLAN_STATUS_AUTH_TIMEOUT 16 ++#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17 ++#define WLAN_STATUS_ASSOC_DENIED_RATES 18 ++/* 802.11b */ ++#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19 ++#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20 ++#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21 ++ ++/* Reason codes */ ++#define WLAN_REASON_UNSPECIFIED 1 ++#define WLAN_REASON_PREV_AUTH_NOT_VALID 2 ++#define WLAN_REASON_DEAUTH_LEAVING 3 ++#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4 ++#define WLAN_REASON_DISASSOC_AP_BUSY 5 ++#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6 ++#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7 ++#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8 ++#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 ++ ++ ++/* Information Element IDs */ ++#define WLAN_EID_SSID 0 ++#define WLAN_EID_SUPP_RATES 1 ++#define WLAN_EID_FH_PARAMS 2 ++#define WLAN_EID_DS_PARAMS 3 ++#define WLAN_EID_CF_PARAMS 4 ++#define WLAN_EID_TIM 5 ++#define WLAN_EID_IBSS_PARAMS 6 ++#define WLAN_EID_CHALLENGE 16 ++#define WLAN_EID_RSN 48 ++#define WLAN_EID_GENERIC 221 ++ ++#define IEEE80211_MGMT_HDR_LEN 24 ++#define IEEE80211_DATA_HDR3_LEN 24 ++#define IEEE80211_DATA_HDR4_LEN 30 ++ ++ ++#define IEEE80211_STATMASK_SIGNAL (1<<0) ++#define IEEE80211_STATMASK_RSSI (1<<1) ++#define IEEE80211_STATMASK_NOISE (1<<2) ++#define IEEE80211_STATMASK_RATE (1<<3) ++#define IEEE80211_STATMASK_WEMASK 0x7 ++ ++ ++#define IEEE80211_CCK_MODULATION (1<<0) ++#define IEEE80211_OFDM_MODULATION (1<<1) ++ ++#define IEEE80211_24GHZ_BAND (1<<0) ++#define IEEE80211_52GHZ_BAND (1<<1) ++ ++#define IEEE80211_CCK_RATE_LEN 4 ++#define IEEE80211_CCK_RATE_1MB 0x02 ++#define IEEE80211_CCK_RATE_2MB 0x04 ++#define IEEE80211_CCK_RATE_5MB 0x0B ++#define IEEE80211_CCK_RATE_11MB 0x16 ++#define IEEE80211_OFDM_RATE_LEN 8 ++#define IEEE80211_OFDM_RATE_6MB 0x0C ++#define IEEE80211_OFDM_RATE_9MB 0x12 ++#define IEEE80211_OFDM_RATE_12MB 0x18 ++#define IEEE80211_OFDM_RATE_18MB 0x24 ++#define IEEE80211_OFDM_RATE_24MB 0x30 ++#define IEEE80211_OFDM_RATE_36MB 0x48 ++#define IEEE80211_OFDM_RATE_48MB 0x60 ++#define IEEE80211_OFDM_RATE_54MB 0x6C ++#define IEEE80211_BASIC_RATE_MASK 0x80 ++ ++#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) ++#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) ++#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) ++#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) ++#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) ++#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) ++#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) ++#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) ++#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) ++#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) ++#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) ++#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) ++ ++#define IEEE80211_CCK_RATES_MASK 0x0000000F ++#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ ++ IEEE80211_CCK_RATE_2MB_MASK) ++#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ ++ IEEE80211_CCK_RATE_5MB_MASK | \ ++ IEEE80211_CCK_RATE_11MB_MASK) ++ ++#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 ++#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ ++ IEEE80211_OFDM_RATE_12MB_MASK | \ ++ IEEE80211_OFDM_RATE_24MB_MASK) ++#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ ++ IEEE80211_OFDM_RATE_9MB_MASK | \ ++ IEEE80211_OFDM_RATE_18MB_MASK | \ ++ IEEE80211_OFDM_RATE_36MB_MASK | \ ++ IEEE80211_OFDM_RATE_48MB_MASK | \ ++ IEEE80211_OFDM_RATE_54MB_MASK) ++#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ ++ IEEE80211_CCK_DEFAULT_RATES_MASK) ++ ++#define IEEE80211_NUM_OFDM_RATES 8 ++#define IEEE80211_NUM_CCK_RATES 4 ++#define IEEE80211_OFDM_SHIFT_MASK_A 4 ++ ++ ++ ++ ++/* NOTE: This data is for statistical purposes; not all hardware provides this ++ * information for frames received. Not setting these will not cause ++ * any adverse affects. */ ++struct ieee80211_rx_stats { ++ u32 mac_time[2]; ++ u8 signalstrength; ++ s8 rssi; ++ u8 signal; ++ u8 noise; ++ u16 rate; /* in 100 kbps */ ++ u8 received_channel; ++ u8 control; ++ u8 mask; ++ u8 freq; ++ u16 len; ++ u8 nic_type; ++}; ++ ++/* IEEE 802.11 requires that STA supports concurrent reception of at least ++ * three fragmented frames. This define can be increased to support more ++ * concurrent frames, but it should be noted that each entry can consume about ++ * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ ++#define IEEE80211_FRAG_CACHE_LEN 4 ++ ++struct ieee80211_frag_entry { ++ unsigned long first_frag_time; ++ unsigned int seq; ++ unsigned int last_frag; ++ struct sk_buff *skb; ++ u8 src_addr[ETH_ALEN]; ++ u8 dst_addr[ETH_ALEN]; ++}; ++ ++struct ieee80211_stats { ++ unsigned int tx_unicast_frames; ++ unsigned int tx_multicast_frames; ++ unsigned int tx_fragments; ++ unsigned int tx_unicast_octets; ++ unsigned int tx_multicast_octets; ++ unsigned int tx_deferred_transmissions; ++ unsigned int tx_single_retry_frames; ++ unsigned int tx_multiple_retry_frames; ++ unsigned int tx_retry_limit_exceeded; ++ unsigned int tx_discards; ++ unsigned int rx_unicast_frames; ++ unsigned int rx_multicast_frames; ++ unsigned int rx_fragments; ++ unsigned int rx_unicast_octets; ++ unsigned int rx_multicast_octets; ++ unsigned int rx_fcs_errors; ++ unsigned int rx_discards_no_buffer; ++ unsigned int tx_discards_wrong_sa; ++ unsigned int rx_discards_undecryptable; ++ unsigned int rx_message_in_msg_fragments; ++ unsigned int rx_message_in_bad_msg_fragments; ++}; ++ ++struct ieee80211_softmac_stats{ ++ unsigned int rx_ass_ok; ++ unsigned int rx_ass_err; ++ unsigned int rx_probe_rq; ++ unsigned int tx_probe_rs; ++ unsigned int tx_beacons; ++ unsigned int rx_auth_rq; ++ unsigned int rx_auth_rs_ok; ++ unsigned int rx_auth_rs_err; ++ unsigned int tx_auth_rq; ++ unsigned int no_auth_rs; ++ unsigned int no_ass_rs; ++ unsigned int tx_ass_rq; ++ unsigned int rx_ass_rq; ++ unsigned int tx_probe_rq; ++ unsigned int reassoc; ++ unsigned int swtxstop; ++ unsigned int swtxawake; ++}; ++ ++struct ieee80211_device; ++ ++#include "ieee80211_crypt.h" ++ ++#define SEC_KEY_1 (1<<0) ++#define SEC_KEY_2 (1<<1) ++#define SEC_KEY_3 (1<<2) ++#define SEC_KEY_4 (1<<3) ++#define SEC_ACTIVE_KEY (1<<4) ++#define SEC_AUTH_MODE (1<<5) ++#define SEC_UNICAST_GROUP (1<<6) ++#define SEC_LEVEL (1<<7) ++#define SEC_ENABLED (1<<8) ++ ++#define SEC_LEVEL_0 0 /* None */ ++#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */ ++#define SEC_LEVEL_2 2 /* Level 1 + TKIP */ ++#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */ ++#define SEC_LEVEL_3 4 /* Level 2 + CCMP */ ++ ++#define WEP_KEYS 4 ++#define WEP_KEY_LEN 13 ++#define ALG_KEY_LEN 32 ++ ++#ifdef _RTL8187_EXT_PATCH_ ++#define MAX_MP 16 ++#endif ++struct ieee80211_security { ++ u16 active_key:2, ++ enabled:1, ++ auth_mode:2, ++ auth_algo:4, ++ unicast_uses_group:1; ++ u8 key_sizes[WEP_KEYS]; ++ u8 keys[WEP_KEYS][ALG_KEY_LEN]; ++ u8 level; ++ u16 flags; ++} __attribute__ ((packed)); ++ ++ ++/* ++ ++ 802.11 data frame from AP ++ ++ ,-------------------------------------------------------------------. ++Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | ++ |------|------|---------|---------|---------|------|---------|------| ++Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | ++ | | tion | (BSSID) | | | ence | data | | ++ `-------------------------------------------------------------------' ++ ++Total: 28-2340 bytes ++ ++*/ ++ ++struct ieee80211_header_data { ++ u16 frame_ctl; ++ u16 duration_id; ++ u8 addr1[6]; ++ u8 addr2[6]; ++ u8 addr3[6]; ++ u16 seq_ctrl; ++}; ++ ++#define BEACON_PROBE_SSID_ID_POSITION 12 ++ ++/* Management Frame Information Element Types */ ++#define MFIE_TYPE_SSID 0 ++#define MFIE_TYPE_RATES 1 ++#define MFIE_TYPE_FH_SET 2 ++#define MFIE_TYPE_DS_SET 3 ++#define MFIE_TYPE_CF_SET 4 ++#define MFIE_TYPE_TIM 5 ++#define MFIE_TYPE_IBSS_SET 6 ++#define MFIE_TYPE_COUNTRY 7 ++#define MFIE_TYPE_CHALLENGE 16 ++#define MFIE_TYPE_ERP 42 ++#define MFIE_TYPE_RSN 48 ++#define MFIE_TYPE_RATES_EX 50 ++#define MFIE_TYPE_GENERIC 221 ++ ++#ifdef ENABLE_DOT11D ++typedef enum ++{ ++ COUNTRY_CODE_FCC = 0, ++ COUNTRY_CODE_IC = 1, ++ COUNTRY_CODE_ETSI = 2, ++ COUNTRY_CODE_SPAIN = 3, ++ COUNTRY_CODE_FRANCE = 4, ++ COUNTRY_CODE_MKK = 5, ++ COUNTRY_CODE_MKK1 = 6, ++ COUNTRY_CODE_ISRAEL = 7, ++ COUNTRY_CODE_TELEC = 8, ++ COUNTRY_CODE_GLOBAL_DOMAIN = 9, ++ COUNTRY_CODE_WORLD_WIDE_13_INDEX = 10 ++}country_code_type_t; ++#endif ++ ++ ++struct ieee80211_info_element_hdr { ++ u8 id; ++ u8 len; ++} __attribute__ ((packed)); ++ ++struct ieee80211_info_element { ++ u8 id; ++ u8 len; ++ u8 data[0]; ++} __attribute__ ((packed)); ++ ++/* ++ * These are the data types that can make up management packets ++ * ++ u16 auth_algorithm; ++ u16 auth_sequence; ++ u16 beacon_interval; ++ u16 capability; ++ u8 current_ap[ETH_ALEN]; ++ u16 listen_interval; ++ struct { ++ u16 association_id:14, reserved:2; ++ } __attribute__ ((packed)); ++ u32 time_stamp[2]; ++ u16 reason; ++ u16 status; ++*/ ++ ++#define IEEE80211_DEFAULT_TX_ESSID "Penguin" ++#define IEEE80211_DEFAULT_BASIC_RATE 10 ++#define IEEE80211_DEFAULT_MESHID "802.11s" ++#define IEEE80211_DEFAULT_MESH_CHAN 1 ++ ++struct ieee80211_authentication { ++ struct ieee80211_header_data header; ++ u16 algorithm; ++ u16 transaction; ++ u16 status; ++ //struct ieee80211_info_element_hdr info_element; ++} __attribute__ ((packed)); ++ ++ ++struct ieee80211_probe_response { ++ struct ieee80211_header_data header; ++ u32 time_stamp[2]; ++ u16 beacon_interval; ++ u16 capability; ++ struct ieee80211_info_element info_element; ++} __attribute__ ((packed)); ++ ++struct ieee80211_probe_request { ++ struct ieee80211_header_data header; ++ /*struct ieee80211_info_element info_element;*/ ++} __attribute__ ((packed)); ++ ++struct ieee80211_assoc_request_frame { ++ struct ieee80211_hdr_3addr header; ++ u16 capability; ++ u16 listen_interval; ++ //u8 current_ap[ETH_ALEN]; ++ struct ieee80211_info_element_hdr info_element; ++} __attribute__ ((packed)); ++ ++struct ieee80211_assoc_response_frame { ++ struct ieee80211_hdr_3addr header; ++ u16 capability; ++ u16 status; ++ u16 aid; ++ struct ieee80211_info_element info_element; /* supported rates */ ++} __attribute__ ((packed)); ++ ++ ++struct ieee80211_txb { ++ u8 nr_frags; ++ u8 encrypted; ++ u16 reserved; ++ u16 frag_size; ++ u16 payload_size; ++ struct sk_buff *fragments[0]; ++}; ++ ++struct ieee80211_wmm_ac_param { ++ u8 ac_aci_acm_aifsn; ++ u8 ac_ecwmin_ecwmax; ++ u16 ac_txop_limit; ++}; ++ ++struct ieee80211_wmm_ts_info { ++ u8 ac_dir_tid; ++ u8 ac_up_psb; ++ u8 reserved; ++} __attribute__ ((packed)); ++ ++struct ieee80211_wmm_tspec_elem { ++ struct ieee80211_wmm_ts_info ts_info; ++ u16 norm_msdu_size; ++ u16 max_msdu_size; ++ u32 min_serv_inter; ++ u32 max_serv_inter; ++ u32 inact_inter; ++ u32 suspen_inter; ++ u32 serv_start_time; ++ u32 min_data_rate; ++ u32 mean_data_rate; ++ u32 peak_data_rate; ++ u32 max_burst_size; ++ u32 delay_bound; ++ u32 min_phy_rate; ++ u16 surp_band_allow; ++ u16 medium_time; ++}__attribute__((packed)); ++ ++enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame}; ++#define MAX_SP_Len (WMM_all_frame << 4) ++#define IEEE80211_QOS_TID 0x0f ++#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5) ++ ++/* SWEEP TABLE ENTRIES NUMBER*/ ++#define MAX_SWEEP_TAB_ENTRIES 42 ++#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 ++/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs ++ * only use 8, and then use extended rates for the remaining supported ++ * rates. Other APs, however, stick all of their supported rates on the ++ * main rates information element... */ ++#define MAX_RATES_LENGTH ((u8)12) ++#define MAX_RATES_EX_LENGTH ((u8)16) ++#define MAX_NETWORK_COUNT 128 ++#ifdef ENABLE_DOT11D ++#define MAX_CHANNEL_NUMBER 165 //YJ,modified,080625 ++#define MAX_IE_LEN 0xFF //+YJ,080625 ++#else ++#define MAX_CHANNEL_NUMBER 161 ++#endif ++ ++//#define IEEE80211_SOFTMAC_SCAN_TIME 400 ++#define IEEE80211_SOFTMAC_SCAN_TIME 100//lzm mod 081209 ++//(HZ / 2) ++#define IEEE80211_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2) ++ ++#define CRC_LENGTH 4U ++ ++#define MAX_WPA_IE_LEN 64 ++ ++#define NETWORK_EMPTY_ESSID (1<<0) ++#define NETWORK_HAS_OFDM (1<<1) ++#define NETWORK_HAS_CCK (1<<2) ++ ++#define IEEE80211_DTIM_MBCAST 4 ++#define IEEE80211_DTIM_UCAST 2 ++#define IEEE80211_DTIM_VALID 1 ++#define IEEE80211_DTIM_INVALID 0 ++ ++#define IEEE80211_PS_DISABLED 0 ++#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST ++#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST ++ ++//added by David for QoS 2006/6/30 ++//#define WMM_Hang_8187 ++#ifdef WMM_Hang_8187 ++#undef WMM_Hang_8187 ++#endif ++ ++#define WME_AC_BE 0x00 ++#define WME_AC_BK 0x01 ++#define WME_AC_VI 0x02 ++#define WME_AC_VO 0x03 ++#define WME_ACI_MASK 0x03 ++#define WME_AIFSN_MASK 0x03 ++#define WME_AC_PRAM_LEN 16 ++ ++//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP ++//#define UP2AC(up) ((up<3) ? ((up==0)?1:0) : (up>>1)) ++#define UP2AC(up) ( \ ++ ((up) < 1) ? WME_AC_BE : \ ++ ((up) < 3) ? WME_AC_BK : \ ++ ((up) < 4) ? WME_AC_BE : \ ++ ((up) < 6) ? WME_AC_VI : \ ++ WME_AC_VO) ++//AC Mapping to UP, using in Tx part for selecting the corresponding TX queue ++#define AC2UP(_ac) ( \ ++ ((_ac) == WME_AC_VO) ? 6 : \ ++ ((_ac) == WME_AC_VI) ? 5 : \ ++ ((_ac) == WME_AC_BK) ? 1 : \ ++ 0) ++ ++#define ETHER_ADDR_LEN 6 /* length of an Ethernet address */ ++struct ether_header { ++ u8 ether_dhost[ETHER_ADDR_LEN]; ++ u8 ether_shost[ETHER_ADDR_LEN]; ++ u16 ether_type; ++} __attribute__((packed)); ++ ++#ifndef ETHERTYPE_PAE ++#define ETHERTYPE_PAE 0x888e /* EAPOL PAE/802.1x */ ++#endif ++#ifndef ETHERTYPE_IP ++#define ETHERTYPE_IP 0x0800 /* IP protocol */ ++#endif ++ ++struct ieee80211_network { ++ /* These entries are used to identify a unique network */ ++ u8 bssid[ETH_ALEN]; ++ u8 channel; ++ /* Ensure null-terminated for any debug msgs */ ++ u8 ssid[IW_ESSID_MAX_SIZE + 1]; ++ u8 ssid_len; ++ ++ /* These are network statistics */ ++ struct ieee80211_rx_stats stats; ++ u16 capability; ++ u8 rates[MAX_RATES_LENGTH]; ++ u8 rates_len; ++ u8 rates_ex[MAX_RATES_EX_LENGTH]; ++ u8 rates_ex_len; ++ unsigned long last_scanned; ++ u8 mode; ++ u8 flags; ++ u32 last_associate; ++ u32 time_stamp[2]; ++ u16 beacon_interval; ++ u16 listen_interval; ++ u16 atim_window; ++ u8 wpa_ie[MAX_WPA_IE_LEN]; ++ size_t wpa_ie_len; ++ u8 rsn_ie[MAX_WPA_IE_LEN]; ++ size_t rsn_ie_len; ++ u8 dtim_period; ++ u8 dtim_data; ++ u32 last_dtim_sta_time[2]; ++#ifdef _RTL8187_EXT_PATCH_ ++ void *ext_entry; ++#endif ++ struct list_head list; ++ //appeded for QoS ++ u8 wmm_info; ++ struct ieee80211_wmm_ac_param wmm_param[4]; ++ u8 QoS_Enable; ++ u8 SignalStrength; ++#ifdef THOMAS_TURBO ++ u8 Turbo_Enable;//enable turbo mode, added by thomas ++#endif ++ ++#ifdef ENABLE_DOT11D ++ u16 CountryIeLen; ++ u8 CountryIeBuf[MAX_IE_LEN]; ++#endif ++ ++}; ++ ++enum ieee80211_state { ++ ++ /* the card is not linked at all */ ++ IEEE80211_NOLINK = 0, ++ ++ /* IEEE80211_ASSOCIATING* are for BSS client mode ++ * the driver shall not perform RX filtering unless ++ * the state is LINKED. ++ * The driver shall just check for the state LINKED and ++ * defaults to NOLINK for ALL the other states (including ++ * LINKED_SCANNING) ++ */ ++ ++ /* the association procedure will start (wq scheduling)*/ ++ IEEE80211_ASSOCIATING, ++ IEEE80211_ASSOCIATING_RETRY, ++ ++ /* the association procedure is sending AUTH request*/ ++ IEEE80211_ASSOCIATING_AUTHENTICATING, ++ ++ /* the association procedure has successfully authentcated ++ * and is sending association request ++ */ ++ IEEE80211_ASSOCIATING_AUTHENTICATED, ++ ++ /* the link is ok. the card associated to a BSS or linked ++ * to a ibss cell or acting as an AP and creating the bss ++ */ ++ IEEE80211_LINKED, ++ ++ /* same as LINKED, but the driver shall apply RX filter ++ * rules as we are in NO_LINK mode. As the card is still ++ * logically linked, but it is doing a syncro site survey ++ * then it will be back to LINKED state. ++ */ ++ IEEE80211_LINKED_SCANNING, ++//by amy for mesh ++ IEEE80211_MESH_SCANNING, ++ IEEE80211_MESH_LINKED, ++//by amy for mesh ++ ++}; ++ ++#define DEFAULT_MAX_SCAN_AGE (15 * HZ) ++#define DEFAULT_FTS 2346 ++#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" ++#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5] ++ ++ ++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11)) ++extern inline int is_multicast_ether_addr(const u8 *addr) ++{ ++ return ((addr[0] != 0xff) && (0x01 & addr[0])); ++} ++#endif ++ ++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)) ++extern inline int is_broadcast_ether_addr(const u8 *addr) ++{ ++ return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \ ++ (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); ++} ++#endif ++ ++#define CFG_IEEE80211_RESERVE_FCS (1<<0) ++#define CFG_IEEE80211_COMPUTE_FCS (1<<1) ++ ++typedef struct tx_pending_t{ ++ int frag; ++ struct ieee80211_txb *txb; ++}tx_pending_t; ++ ++#ifdef _RTL8187_EXT_PATCH_ ++struct ieee80211_crypt_data_list{ ++ u8 used; ++ u8 mac_addr[ETH_ALEN]; //record mac_add ++ struct ieee80211_crypt_data *crypt[WEP_KEYS]; ++}__attribute__((packed)); ++ ++#endif ++ ++struct ieee80211_device { ++ struct net_device *dev; ++ ++ /* Bookkeeping structures */ ++ struct net_device_stats stats; ++ struct ieee80211_stats ieee_stats; ++ struct ieee80211_softmac_stats softmac_stats; ++ ++ /* Probe / Beacon management */ ++ struct list_head network_free_list; ++ struct list_head network_list; ++ struct ieee80211_network *networks; ++ int scans; ++ int scan_age; ++ ++ int iw_mode; /* operating mode (IW_MODE_*) */ ++#ifdef _RTL8187_EXT_PATCH_ ++ int iw_ext_mode; // if iw_mode == iw_ext_mode, do ext_patch_**(); ++#endif ++ ++ spinlock_t lock; ++ spinlock_t wpax_suitlist_lock; ++ ++ int tx_headroom; /* Set to size of any additional room needed at front ++ * of allocated Tx SKBs */ ++ u32 config; ++ ++ /* WEP and other encryption related settings at the device level */ ++ int open_wep; /* Set to 1 to allow unencrypted frames */ ++ ++ int reset_on_keychange; /* Set to 1 if the HW needs to be reset on ++ * WEP key changes */ ++ ++ /* If the host performs {en,de}cryption, then set to 1 */ ++ int host_encrypt; ++ int host_decrypt; ++ int ieee802_1x; /* is IEEE 802.1X used */ ++ ++ /* WPA data */ ++ int wpa_enabled; ++ int drop_unencrypted; ++ int tkip_countermeasures; ++ int privacy_invoked; ++ size_t wpa_ie_len; ++ u8 *wpa_ie; ++ ++//#ifdef JOHN_TKIP ++ u8 ap_mac_addr[6]; ++ u16 pairwise_key_type; ++ u16 broadcast_key_type; ++//#endif ++ struct list_head crypt_deinit_list; ++#ifdef _RTL8187_EXT_PATCH_ ++ struct ieee80211_crypt_data_list* cryptlist[MAX_MP]; ++#else ++ struct ieee80211_crypt_data *crypt[WEP_KEYS]; ++#endif ++ int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */ ++ struct timer_list crypt_deinit_timer; ++ ++ int bcrx_sta_key; /* use individual keys to override default keys even ++ * with RX of broad/multicast frames */ ++ ++ /* Fragmentation structures */ ++ // each streaming contain a entry ++ struct ieee80211_frag_entry frag_cache[17][IEEE80211_FRAG_CACHE_LEN]; ++ unsigned int frag_next_idx[17]; ++ u16 fts; /* Fragmentation Threshold */ ++ ++ /* This stores infos for the current network. ++ * Either the network we are associated in INFRASTRUCTURE ++ * or the network that we are creating in MASTER mode. ++ * ad-hoc is a mixture ;-). ++ * Note that in infrastructure mode, even when not associated, ++ * fields bssid and essid may be valid (if wpa_set and essid_set ++ * are true) as thy carry the value set by the user via iwconfig ++ */ ++ struct ieee80211_network current_network; ++ ++ ++ enum ieee80211_state state; ++ ++ int short_slot; ++ int mode; /* A, B, G */ ++ int modulation; /* CCK, OFDM */ ++ int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */ ++ int abg_true; /* ABG flag */ ++ ++ /* used for forcing the ibss workqueue to terminate ++ * without wait for the syncro scan to terminate ++ */ ++ short sync_scan_hurryup; ++ ++#ifdef ENABLE_DOT11D ++ void * pDot11dInfo; ++ bool bGlobalDomain; ++ bool bWorldWide13;//lzm add 20081205 ++ ++ // For Liteon Ch12~13 passive scan ++ u8 MinPassiveChnlNum; ++ u8 IbssStartChnl; ++#else ++ /* map of allowed channels. 0 is dummy */ ++ // FIXME: remeber to default to a basic channel plan depending of the PHY type ++ int channel_map[MAX_CHANNEL_NUMBER+1]; ++#endif ++ ++ int rate; /* current rate */ ++ int basic_rate; ++ //FIXME: pleace callback, see if redundant with softmac_features ++ short active_scan; ++ ++#ifdef _RTL8187_EXT_PATCH_ ++// short ch_lock; ++ short meshScanMode; ++#endif ++ /* this contains flags for selectively enable softmac support */ ++ u16 softmac_features; ++ ++ /* if the sequence control field is not filled by HW */ ++ u16 seq_ctrl[5]; ++ ++ /* association procedure transaction sequence number */ ++ u16 associate_seq; ++ ++ /* AID for RTXed association responses */ ++ u16 assoc_id; ++ ++ /* power save mode related*/ ++ short ps; ++ short sta_sleep; ++ int ps_timeout; ++ struct tasklet_struct ps_task; ++ u32 ps_th; ++ u32 ps_tl; ++ ++ short raw_tx; ++ /* used if IEEE_SOFTMAC_TX_QUEUE is set */ ++ short queue_stop; ++ short scanning; ++ short scan_watchdog;//lzm add 081215 for roaming ++ short proto_started; ++ ++ struct semaphore wx_sem; ++ struct semaphore scan_sem; ++ struct semaphore ips_sem; ++ spinlock_t mgmt_tx_lock; ++ spinlock_t beacon_lock; ++ spinlock_t beaconflag_lock; ++ short beacon_txing; ++ ++ short wap_set; ++ short ssid_set; ++ ++ u8 wpax_type_set; //{added by David, 2006.9.28} ++ u32 wpax_type_notify; //{added by David, 2006.9.26} ++ ++ /* QoS related flag */ ++ char init_wmmparam_flag; ++ ++ /* for discarding duplicated packets in IBSS */ ++ struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE]; ++ ++ /* for discarding duplicated packets in Mesh */ //added by david 2008.2.28/ ++ struct list_head mesh_mac_hash[IEEE_MESH_MAC_HASH_SIZE]; ++ ++ /* for discarding duplicated packets in BSS */ ++ u16 last_rxseq_num[17]; /* rx seq previous per-tid */ ++ u16 last_rxfrag_num[17];/* tx frag previous per-tid */ ++ unsigned long last_packet_time[17]; ++ ++ /* for PS mode */ ++ unsigned long last_rx_ps_time; ++ ++ /* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */ ++ struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM]; ++ int mgmt_queue_head; ++ int mgmt_queue_tail; ++//by amy for ps ++ bool bInactivePs; ++ bool actscanning; ++ u16 ListenInterval; ++ u32 NumRxData; ++ unsigned long NumRxDataInPeriod; //YJ,add,080828 ++ unsigned long NumRxBcnInPeriod; //YJ,add,080828 ++//by amy for ps ++ short meshid_set; ++ /* used if IEEE_SOFTMAC_TX_QUEUE is set */ ++ struct tx_pending_t tx_pending; ++ ++ /* used if IEEE_SOFTMAC_ASSOCIATE is set */ ++ struct timer_list associate_timer; ++ ++ /* used if IEEE_SOFTMAC_BEACONS is set */ ++ struct timer_list beacon_timer; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ struct work_struct associate_complete_wq; ++// struct work_struct associate_retry_wq; ++// struct work_struct start_ibss_wq; ++ struct work_struct associate_procedure_wq; ++ struct work_struct ips_leave_wq; //YJ,add,081230,for IPS ++ bool bHwRadioOff;//by lizhaoming ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++ struct delayed_work softmac_scan_wq; ++ struct delayed_work start_ibss_wq; ++ struct delayed_work associate_retry_wq; ++//by amy for rate adaptive ++ struct delayed_work rate_adapter_wq; ++//by amy for rate adaptive ++ struct delayed_work watch_dog_wq; ++ struct delayed_work hw_dig_wq; ++ struct delayed_work tx_pw_wq; ++ ++//Added for RF power on power off by lizhaoming 080512 ++#ifdef POLLING_METHOD_FOR_RADIO ++ struct delayed_work GPIOChangeRFWorkItem; ++#endif ++ ++#ifdef SW_ANTE_DIVERSITY ++ struct delayed_work SwAntennaWorkItem; ++#endif ++ ++#else ++ struct work_struct softmac_scan_wq; ++ struct work_struct start_ibss_wq; ++ struct work_struct associate_retry_wq; ++//by amy for rate adaptive ++ struct work_struct rate_adapter_wq; ++//by amy for rate adaptive ++ struct work_struct watch_dog_wq; ++ struct work_struct hw_dig_wq; ++ struct work_struct tx_pw_wq; ++ ++//Added for RF power on power off by lizhaoming 080512 ++#ifdef POLLING_METHOD_FOR_RADIO ++ struct work_struct GPIOChangeRFWorkItem; ++#endif ++ ++#ifdef SW_ANTE_DIVERSITY ++ struct work_struct SwAntennaWorkItem; ++#endif ++ ++#endif ++ ++//struct work_struct softmac_scan_wq; ++ struct work_struct wx_sync_scan_wq; ++ struct work_struct wmm_param_update_wq; ++#ifdef _RTL8187_EXT_PATCH_ ++ struct work_struct ext_stop_scan_wq; ++ struct work_struct ext_send_beacon_wq; ++#endif ++ struct workqueue_struct *wq; ++#else ++ /* used for periodly scan */ ++ struct timer_list scan_timer; ++ ++ struct tq_struct associate_complete_wq; ++ struct tq_struct associate_retry_wq; ++ struct tq_struct start_ibss_wq; ++ struct tq_struct associate_procedure_wq; ++ struct tq_struct ips_leave_wq; //YJ,add,081230,for IPS ++ struct tq_struct softmac_scan_wq; ++ struct tq_struct wx_sync_scan_wq; ++ struct tq_struct wmm_param_update_wq; ++#ifdef _RTL8187_EXT_PATCH_ ++ struct tq_struct ext_stop_scan_wq; ++ struct tq_struct ext_send_beacon_wq; ++#endif ++#endif ++ ++ /* Callback functions */ ++ void (*set_security)(struct net_device *dev, ++ struct ieee80211_security *sec); ++ ++ /* Used to TX data frame by using txb structs. ++ * this is not used if in the softmac_features ++ * is set the flag IEEE_SOFTMAC_TX_QUEUE ++ */ ++ int (*hard_start_xmit)(struct ieee80211_txb *txb, ++ struct net_device *dev); ++ ++ int (*reset_port)(struct net_device *dev); ++ ++ /* Softmac-generated frames (mamagement) are TXed via this ++ * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is ++ * not set. As some cards may have different HW queues that ++ * one might want to use for data and management frames ++ * the option to have two callbacks might be useful. ++ * This fucntion can't sleep. ++ */ ++ int (*softmac_hard_start_xmit)(struct sk_buff *skb, ++ struct net_device *dev); ++ ++ /* used instead of hard_start_xmit (not softmac_hard_start_xmit) ++ * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data ++ * frames. I the option IEEE_SOFTMAC_SINGLE_QUEUE is also set ++ * then also management frames are sent via this callback. ++ * This function can't sleep. ++ */ ++ void (*softmac_data_hard_start_xmit)(struct sk_buff *skb, ++ struct net_device *dev,int rate); ++ ++ /* stops the HW queue for DATA frames. Useful to avoid ++ * waste time to TX data frame when we are reassociating ++ * This function can sleep. ++ */ ++ void (*data_hard_stop)(struct net_device *dev); ++ ++ /* OK this is complementar to data_poll_hard_stop */ ++ void (*data_hard_resume)(struct net_device *dev); ++ ++ /* ask to the driver to retune the radio . ++ * This function can sleep. the driver should ensure ++ * the radio has been swithced before return. ++ */ ++ void (*set_chan)(struct net_device *dev,short ch); ++ ++ /* These are not used if the ieee stack takes care of ++ * scanning (IEEE_SOFTMAC_SCAN feature set). ++ * In this case only the set_chan is used. ++ * ++ * The syncro version is similar to the start_scan but ++ * does not return until all channels has been scanned. ++ * this is called in user context and should sleep, ++ * it is called in a work_queue when swithcing to ad-hoc mode ++ * or in behalf of iwlist scan when the card is associated ++ * and root user ask for a scan. ++ * the fucntion stop_scan should stop both the syncro and ++ * background scanning and can sleep. ++ * The fucntion start_scan should initiate the background ++ * scanning and can't sleep. ++ */ ++ void (*scan_syncro)(struct net_device *dev); ++ void (*start_scan)(struct net_device *dev); ++ void (*stop_scan)(struct net_device *dev); ++ ++ /* indicate the driver that the link state is changed ++ * for example it may indicate the card is associated now. ++ * Driver might be interested in this to apply RX filter ++ * rules or simply light the LINK led ++ */ ++ void (*link_change)(struct net_device *dev); ++ ++ /* these two function indicates to the HW when to start ++ * and stop to send beacons. This is used when the ++ * IEEE_SOFTMAC_BEACONS is not set. For now the ++ * stop_send_bacons is NOT guaranteed to be called only ++ * after start_send_beacons. ++ */ ++ void (*start_send_beacons) (struct net_device *dev); ++ void (*stop_send_beacons) (struct net_device *dev); ++ ++ /* power save mode related */ ++ void (*sta_wake_up) (struct net_device *dev); ++ void (*ps_request_tx_ack) (struct net_device *dev); ++ void (*enter_sleep_state) (struct net_device *dev, u32 th, u32 tl); ++ short (*ps_is_queue_empty) (struct net_device *dev); ++ ++//by lizhaoming for LED 2008.6.23 ++#ifdef LED ++ void (*ieee80211_led_contorl) (struct net_device *dev, LED_CTL_MODE LedAction); ++#endif ++#ifdef CONFIG_IPS ++ void (*ieee80211_ips_leave) (struct net_device *dev); ++#endif ++ /* QoS related */ ++ //void (*wmm_param_update) (struct net_device *dev, u8 *ac_param); ++ //void (*wmm_param_update) (struct ieee80211_device *ieee); ++ ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ ++ /// ieee80211_softmac.c ++ int (*ext_patch_ieee80211_start_protocol) (struct ieee80211_device *ieee); // start special mode ++ ++ short (*ext_patch_ieee80211_probe_req_1) (struct ieee80211_device *ieee); // return = 0: no more phases, >0: another phase ++ u8* (*ext_patch_ieee80211_probe_req_2) (struct ieee80211_device *ieee, struct sk_buff *skb, u8 *tag); // return tag ++ ++ void (*ext_patch_ieee80211_stop_protocol) (struct ieee80211_device *ieee); // stop timer ++ ++ void (*ext_patch_ieee80211_association_req_1) (struct ieee80211_assoc_request_frame *hdr); ++ u8* (*ext_patch_ieee80211_association_req_2) (struct ieee80211_device *ieee, struct ieee80211_network *pstat, struct sk_buff *skb); ++ ++ int (*ext_patch_ieee80211_rx_frame_softmac_on_assoc_req) (struct ieee80211_device *ieee, struct sk_buff *skb); ++ int (*ext_patch_ieee80211_rx_frame_softmac_on_assoc_rsp) (struct ieee80211_device *ieee, struct sk_buff *skb); ++ ++ void (*ext_patch_ieee80211_assoc_resp_by_net_1) (struct ieee80211_assoc_response_frame *assoc); ++ u8* (*ext_patch_ieee80211_assoc_resp_by_net_2) (struct ieee80211_device *ieee, struct ieee80211_network *pstat, int pkt_type, struct sk_buff *skb); ++ ++ int (*ext_patch_ieee80211_ext_stop_scan_wq_set_channel) (struct ieee80211_device *ieee); ++ ++ int (*ext_patch_ieee80211_softmac_xmit_get_rate) (struct ieee80211_device *ieee, struct sk_buff *skb); ++ ++ int (*ext_patch_ieee80211_rx_frame_softmac_on_auth)(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats); ++ int (*ext_patch_ieee80211_rx_frame_softmac_on_deauth)(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats); ++//by amy for mesh ++ void (*ext_patch_ieee80211_start_mesh)(struct ieee80211_device *ieee); ++//by amy for mesh ++ // ieee80211_rx.c ++ // rz ++ void (*ext_patch_ieee80211_rx_mgt_on_probe_req) ( struct ieee80211_device *ieee, struct ieee80211_probe_request *beacon, struct ieee80211_rx_stats *stats); ++ unsigned int(*ext_patch_ieee80211_process_probe_response_1)(struct ieee80211_device *ieee, struct ieee80211_probe_response *beacon, struct ieee80211_rx_stats *stats); ++ ++ void (*ext_patch_ieee80211_rx_mgt_update_expire) ( struct ieee80211_device *ieee, struct sk_buff *skb); ++ struct sk_buff* (*ext_patch_get_beacon_get_probersp)(struct ieee80211_device *ieee, u8 *dest, struct ieee80211_network *net); ++ ++ // success(return 0) is responsible to free skb ++ int (*ext_patch_ieee80211_rx_on_rx) (struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats, u16 type, u16 stype); ++ ++ int (*ext_patch_ieee80211_rx_frame_get_hdrlen) (struct ieee80211_device *ieee, struct sk_buff *skb); ++ ++ // Check whether or not accept the incoming frame. return 0: not accept, >0: accept ++ int (*ext_patch_ieee80211_rx_is_valid_framectl) (struct ieee80211_device *ieee, u16 fc, u16 type, u16 stype); ++ ++ // return > 0 is success. 0 when failed ++ // success(return >0) is responsible to free skb ++ int (*ext_patch_ieee80211_rx_process_dataframe) (struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats); ++ ++ /* added by david for setting acl dynamically */ ++ u8 (*ext_patch_ieee80211_acl_query) (struct ieee80211_device *ieee, u8 *sa); ++ ++ // int (*ext_patch_is_duplicate_packet) (struct ieee80211_device *ieee, struct ieee80211_hdr *header, u16 type, u16 stype); ++ ++ // ieee80211_tx.c ++ ++ // locked by ieee->lock. Call ieee80211_softmac_xmit afterward ++ struct ieee80211_txb* (*ext_patch_ieee80211_xmit) (struct sk_buff *skb, struct net_device *dev); ++ ++ ++#endif // _RTL8187_EXT_PATCH_ ++ ++ /* This must be the last item so that it points to the data ++ * allocated beyond this structure by alloc_ieee80211 */ ++ u8 priv[0]; ++}; ++ ++#define IEEE_A (1<<0) ++#define IEEE_B (1<<1) ++#define IEEE_G (1<<2) ++#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G) ++ ++/* Generate a 802.11 header */ ++ ++/* Uses the channel change callback directly ++ * instead of [start/stop] scan callbacks ++ */ ++#define IEEE_SOFTMAC_SCAN (1<<2) ++ ++/* Perform authentication and association handshake */ ++#define IEEE_SOFTMAC_ASSOCIATE (1<<3) ++ ++/* Generate probe requests */ ++#define IEEE_SOFTMAC_PROBERQ (1<<4) ++ ++/* Generate respones to probe requests */ ++#define IEEE_SOFTMAC_PROBERS (1<<5) ++ ++/* The ieee802.11 stack will manages the netif queue ++ * wake/stop for the driver, taking care of 802.11 ++ * fragmentation. See softmac.c for details. */ ++#define IEEE_SOFTMAC_TX_QUEUE (1<<7) ++ ++/* Uses only the softmac_data_hard_start_xmit ++ * even for TX management frames. ++ */ ++#define IEEE_SOFTMAC_SINGLE_QUEUE (1<<8) ++ ++/* Generate beacons. The stack will enqueue beacons ++ * to the card ++ */ ++#define IEEE_SOFTMAC_BEACONS (1<<6) ++#ifdef _RTL8187_EXT_PATCH_ ++extern inline int ieee80211_find_MP(struct ieee80211_device* ieee, const u8* addr, u8 set) ++{ ++ int i=0; ++ for (i=1; icryptlist[i]->used == 0)&&set) ++ {//entry is empty ++ memcpy(ieee->cryptlist[i]->mac_addr, addr, ETH_ALEN); ++ ieee->cryptlist[i]->used = 1; ++ return i; ++ } ++ else if (0 == memcmp(ieee->cryptlist[i]->mac_addr, addr, ETH_ALEN)) //find matched entry ++ { ++ return i; ++ } ++ } ++ return -1; ++} ++#endif ++ ++ ++ ++static inline void *ieee80211_priv(struct net_device *dev) ++{ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ return ((struct ieee80211_device *)netdev_priv(dev))->priv; ++#else ++ return ((struct ieee80211_device *)dev->priv)->priv; ++#endif ++} ++ ++extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len) ++{ ++ /* Single white space is for Linksys APs */ ++ if (essid_len == 1 && essid[0] == ' ') ++ return 1; ++ ++ /* Otherwise, if the entire essid is 0, we assume it is hidden */ ++ while (essid_len) { ++ essid_len--; ++ if (essid[essid_len] != '\0') ++ return 0; ++ } ++ ++ return 1; ++} ++ ++extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode) ++{ ++ /* ++ * It is possible for both access points and our device to support ++ * combinations of modes, so as long as there is one valid combination ++ * of ap/device supported modes, then return success ++ * ++ */ ++ if ((mode & IEEE_A) && ++ (ieee->modulation & IEEE80211_OFDM_MODULATION) && ++ (ieee->freq_band & IEEE80211_52GHZ_BAND)) ++ return 1; ++ ++ if ((mode & IEEE_G) && ++ (ieee->modulation & IEEE80211_OFDM_MODULATION) && ++ (ieee->freq_band & IEEE80211_24GHZ_BAND)) ++ return 1; ++ ++ if ((mode & IEEE_B) && ++ (ieee->modulation & IEEE80211_CCK_MODULATION) && ++ (ieee->freq_band & IEEE80211_24GHZ_BAND)) ++ return 1; ++ ++ return 0; ++} ++ ++extern inline int ieee80211_get_hdrlen(u16 fc) ++{ ++ int hdrlen = 24; ++ ++ switch (WLAN_FC_GET_TYPE(fc)) { ++ case IEEE80211_FTYPE_DATA: ++ if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) ++ hdrlen = 30; /* Addr4 */ ++ if(IEEE80211_QOS_HAS_SEQ(fc)) ++ hdrlen += 2; /* QOS ctrl*/ ++ break; ++ case IEEE80211_FTYPE_CTL: ++ switch (WLAN_FC_GET_STYPE(fc)) { ++ case IEEE80211_STYPE_CTS: ++ case IEEE80211_STYPE_ACK: ++ hdrlen = 10; ++ break; ++ default: ++ hdrlen = 16; ++ break; ++ } ++ break; ++ } ++ ++ return hdrlen; ++} ++ ++ ++ ++/* ieee80211.c */ ++extern void free_ieee80211(struct net_device *dev); ++extern struct net_device *alloc_ieee80211(int sizeof_priv); ++ ++extern int ieee80211_set_encryption(struct ieee80211_device *ieee); ++ ++/* ieee80211_tx.c */ ++ ++extern int ieee80211_encrypt_fragment( ++ struct ieee80211_device *ieee, ++ struct sk_buff *frag, ++ int hdr_len); ++ ++extern int ieee80211_xmit(struct sk_buff *skb, ++ struct net_device *dev); ++extern void ieee80211_txb_free(struct ieee80211_txb *); ++ ++ ++/* ieee80211_rx.c */ ++extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, ++ struct ieee80211_rx_stats *rx_stats); ++extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, ++ struct ieee80211_hdr *header, ++ struct ieee80211_rx_stats *stats); ++ ++/* ieee80211_wx.c */ ++extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *key); ++extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *key); ++extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *key); ++extern int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data* wrqu, char *extra); ++int ieee80211_wx_set_auth(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ struct iw_param *data, char *extra); ++int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra); ++ ++int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len); ++/* ieee80211_softmac.c */ ++extern short ieee80211_is_54g(struct ieee80211_network net); ++extern short ieee80211_is_shortslot(struct ieee80211_network net); ++extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, ++ struct ieee80211_rx_stats *rx_stats, u16 type, ++ u16 stype); ++extern void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net); ++ ++extern void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee); ++extern void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee); ++extern void ieee80211_start_bss(struct ieee80211_device *ieee); ++extern void ieee80211_start_master_bss(struct ieee80211_device *ieee); ++extern void ieee80211_start_ibss(struct ieee80211_device *ieee); ++extern void ieee80211_softmac_init(struct ieee80211_device *ieee); ++extern void ieee80211_softmac_free(struct ieee80211_device *ieee); ++extern void ieee80211_associate_abort(struct ieee80211_device *ieee); ++extern void ieee80211_disassociate(struct ieee80211_device *ieee); ++extern void ieee80211_stop_scan(struct ieee80211_device *ieee); ++extern void ieee80211_start_scan_syncro(struct ieee80211_device *ieee); ++extern void ieee80211_check_all_nets(struct ieee80211_device *ieee); ++extern void ieee80211_start_protocol(struct ieee80211_device *ieee); ++extern void ieee80211_stop_protocol(struct ieee80211_device *ieee); ++extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee); ++extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee); ++extern void ieee80211_reset_queue(struct ieee80211_device *ieee); ++extern void ieee80211_wake_queue(struct ieee80211_device *ieee); ++extern void ieee80211_stop_queue(struct ieee80211_device *ieee); ++extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee); ++extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee); ++extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee); ++extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p); ++extern void notify_wx_assoc_event(struct ieee80211_device *ieee); ++extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success); ++extern void ieee80211_start_scan(struct ieee80211_device *ieee); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++extern void ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb); ++extern void ieee80211_ext_issue_assoc_req(struct ieee80211_device *ieee, struct ieee80211_network *pstat); ++extern void ieee80211_associate_step1(struct ieee80211_device *ieee); ++extern void ieee80211_ext_issue_disassoc(struct ieee80211_device *ieee, struct ieee80211_network *pstat, int reason, unsigned char extReason); ++extern void ieee80211_ext_issue_assoc_rsp(struct ieee80211_device *ieee, u8 *dest, unsigned short status, struct ieee80211_network *pstat, int pkt_type); ++extern void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee); ++extern struct sk_buff* ieee80211_ext_probe_resp_by_net(struct ieee80211_device *ieee, u8 *dest, struct ieee80211_network *net); ++extern int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response *beacon, struct ieee80211_network *network, struct ieee80211_rx_stats *stats); ++extern struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, int gfp_mask); ++extern void ieee80211_ext_send_11s_beacon(struct ieee80211_device *ieee); ++extern struct ieee80211_txb *ieee80211_ext_alloc_txb(struct sk_buff *skb, struct net_device *dev, struct ieee80211_hdr_3addr *header, int hdr_len, u8 isQoS, u16 *pQOS_ctl, int isEncrypt, struct ieee80211_crypt_data* crypt); ++extern struct ieee80211_txb *ieee80211_ext_reuse_txb(struct sk_buff *skb, struct net_device *dev, struct ieee80211_hdr_3addr *header, int hdr_len, u8 isQoS, u16 *pQOS_ctl, int isEncrypt, struct ieee80211_crypt_data* crypt); ++extern int ieee_ext_skb_p80211_to_ether(struct sk_buff *skb, int hdrlen, u8 *dst, u8 *src); ++#endif ++ ++/* ieee80211_crypt_ccmp&tkip&wep.c */ ++extern void ieee80211_tkip_null(void); ++extern void ieee80211_wep_null(void); ++extern void ieee80211_ccmp_null(void); ++/* ieee80211_softmac_wx.c */ ++ ++extern int ieee80211_wx_get_wap(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *ext); ++ ++extern int ieee80211_wx_set_wap(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *awrq, ++ char *extra); ++ ++extern int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b); ++ ++extern int ieee80211_wx_set_rate(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra); ++ ++extern int ieee80211_wx_get_rate(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra); ++ ++extern int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b); ++ ++extern int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b); ++ ++extern int ieee80211_wx_set_essid(struct ieee80211_device *ieee, ++ struct iw_request_info *a, ++ union iwreq_data *wrqu, char *extra); ++ ++extern int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b); ++ ++extern int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b); ++ ++extern int ieee80211_wx_get_freq(struct ieee80211_device *ieee, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b); ++ ++//extern void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++extern void ieee80211_wx_sync_scan_wq(struct work_struct *work); ++#else ++ extern void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee); ++#endif ++extern int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra); ++ ++extern int ieee80211_wx_get_name(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra); ++ ++extern int ieee80211_wx_set_power(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra); ++ ++extern int ieee80211_wx_get_power(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra); ++ ++extern const long ieee80211_wlan_frequencies[]; ++ ++extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee) ++{ ++ ieee->scans++; ++} ++ ++extern inline int ieee80211_get_scans(struct ieee80211_device *ieee) ++{ ++ return ieee->scans; ++} ++ ++static inline const char *escape_essid(const char *essid, u8 essid_len) { ++ static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; ++ const char *s = essid; ++ char *d = escaped; ++ ++ if (ieee80211_is_empty_essid(essid, essid_len)) { ++ memcpy(escaped, "", sizeof("")); ++ return escaped; ++ } ++ ++ essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE); ++ while (essid_len--) { ++ if (*s == '\0') { ++ *d++ = '\\'; ++ *d++ = '0'; ++ s++; ++ } else { ++ *d++ = *s++; ++ } ++ } ++ *d = '\0'; ++ return escaped; ++} ++#endif /* IEEE80211_H */ +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_module.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_module.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_module.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_module.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,385 @@ ++/******************************************************************************* ++ ++ Copyright(c) 2004 Intel Corporation. All rights reserved. ++ ++ Portions of this file are based on the WEP enablement code provided by the ++ Host AP project hostap-drivers v0.1.3 ++ Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen ++ ++ Copyright (c) 2002-2003, Jouni Malinen ++ ++ This program is free software; you can redistribute it and/or modify it ++ under the terms of version 2 of the GNU General Public License as ++ published by the Free Software Foundation. ++ ++ This program is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., 59 ++ Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++ The full GNU General Public License is included in this distribution in the ++ file called LICENSE. ++ ++ Contact Information: ++ James P. Ketrenos ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#include ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ieee80211.h" ++ ++MODULE_DESCRIPTION("802.11 data/management/control stack"); ++MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation "); ++MODULE_LICENSE("GPL"); ++ ++#define DRV_NAME "ieee80211" ++ ++static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee) ++{ ++ if (ieee->networks) ++ return 0; ++ ++ ieee->networks = kmalloc( ++ MAX_NETWORK_COUNT * sizeof(struct ieee80211_network), ++ GFP_KERNEL); ++ if (!ieee->networks) { ++ printk(KERN_WARNING "%s: Out of memory allocating beacons\n", ++ ieee->dev->name); ++ return -ENOMEM; ++ } ++ ++ memset(ieee->networks, 0, ++ MAX_NETWORK_COUNT * sizeof(struct ieee80211_network)); ++ ++ return 0; ++} ++ ++static inline void ieee80211_networks_free(struct ieee80211_device *ieee) ++{ ++ if (!ieee->networks) ++ return; ++ kfree(ieee->networks); ++ ieee->networks = NULL; ++} ++ ++static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee) ++{ ++ int i; ++ ++ INIT_LIST_HEAD(&ieee->network_free_list); ++ INIT_LIST_HEAD(&ieee->network_list); ++ for (i = 0; i < MAX_NETWORK_COUNT; i++) ++ list_add_tail(&ieee->networks[i].list, &ieee->network_free_list); ++} ++ ++ ++struct net_device *alloc_ieee80211(int sizeof_priv) ++{ ++ struct ieee80211_device *ieee; ++ struct net_device *dev; ++ int i,err; ++ ++ IEEE80211_DEBUG_INFO("Initializing...\n"); ++ ++ dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv); ++ if (!dev) { ++ IEEE80211_ERROR("Unable to network device.\n"); ++ goto failed; ++ } ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) ++ ieee = netdev_priv(dev); ++#else ++ ieee = (struct ieee80211_device *)dev->priv; ++#endif ++ ++ ieee->dev = dev; ++ ++ err = ieee80211_networks_allocate(ieee); ++ if (err) { ++ IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", ++ err); ++ goto failed; ++ } ++ ieee80211_networks_initialize(ieee); ++ ++ /* Default fragmentation threshold is maximum payload size */ ++ ieee->fts = DEFAULT_FTS; ++ ieee->scan_age = DEFAULT_MAX_SCAN_AGE; ++ ieee->open_wep = 1; ++ ++ /* Default to enabling full open WEP with host based encrypt/decrypt */ ++ ieee->host_encrypt = 1; ++ ieee->host_decrypt = 1; ++ ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ ++ ++ INIT_LIST_HEAD(&ieee->crypt_deinit_list); ++ init_timer(&ieee->crypt_deinit_timer); ++ ieee->crypt_deinit_timer.data = (unsigned long)ieee; ++ ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler; ++ ++ spin_lock_init(&ieee->lock); ++ spin_lock_init(&ieee->wpax_suitlist_lock); ++ ++ ieee->wpax_type_set = 0; ++ ieee->wpa_enabled = 0; ++ ieee->tkip_countermeasures = 0; ++ ieee->drop_unencrypted = 0; ++ ieee->privacy_invoked = 0; ++ ieee->ieee802_1x = 1; ++ ieee->raw_tx = 0; ++#ifdef _RTL8187_EXT_PATCH_ ++ for (i=0; icryptlist[i] = (struct ieee80211_crypt_data_list*) kmalloc(sizeof(struct ieee80211_crypt_data_list), GFP_KERNEL); ++ if (NULL == ieee->cryptlist[i]) ++ { ++ printk("error kmalloc cryptlist\n"); ++ goto failed; ++ } ++ memset(ieee->cryptlist[i], 0, sizeof(struct ieee80211_crypt_data_list)); ++ ++ } ++#endif ++ ieee80211_softmac_init(ieee); ++ ++ for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) ++ INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]); ++ ++ for (i = 0; i < IEEE_MESH_MAC_HASH_SIZE; i++) ++ INIT_LIST_HEAD(&ieee->mesh_mac_hash[i]); ++ ++ for (i = 0; i < 17; i++) { ++ ieee->last_rxseq_num[i] = -1; ++ ieee->last_rxfrag_num[i] = -1; ++ ieee->last_packet_time[i] = 0; ++ } ++#if 1 //added these to autoload encryption module. WB ++ ieee80211_tkip_null(); ++ ieee80211_wep_null(); ++ ieee80211_ccmp_null(); ++#endif ++ return dev; ++ ++ failed: ++#ifdef _RTL8187_EXT_PATCH_ ++ for (i=0; icryptlist[i]==NULL){ ++ continue; ++ } ++ kfree(ieee->cryptlist[i]); ++ ieee->cryptlist[i] = NULL; ++ ++ } ++#endif ++ if (dev) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) ++ free_netdev(dev); ++#else ++ kfree(dev); ++#endif ++ return NULL; ++} ++ ++ ++void free_ieee80211(struct net_device *dev) ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) ++ struct ieee80211_device *ieee = netdev_priv(dev); ++#else ++ struct ieee80211_device *ieee = (struct ieee80211_device *)dev->priv; ++#endif ++ int i;//,j; ++ struct list_head *p, *q; ++ ++ ++ ieee80211_softmac_free(ieee); ++ del_timer_sync(&ieee->crypt_deinit_timer); ++ ieee80211_crypt_deinit_entries(ieee, 1); ++#if 1 ++ ieee80211_tkip_null(); ++ ieee80211_wep_null(); ++ ieee80211_ccmp_null(); ++#endif ++ for (i = 0; i < WEP_KEYS; i++) { ++#ifdef _RTL8187_EXT_PATCH_ ++{ ++ // int j; ++ for (j=0;jcryptlist[j] == NULL) ++ continue; ++ struct ieee80211_crypt_data *crypt = ieee->cryptlist[j]->crypt[i]; ++#else ++ struct ieee80211_crypt_data *crypt = ieee->crypt[i]; ++#endif ++ if (crypt) { ++ if (crypt->ops) { ++ crypt->ops->deinit(crypt->priv); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ++ module_put(crypt->ops->owner); ++#else ++ __MOD_DEC_USE_COUNT(crypt->ops->owner); ++#endif ++ } ++ kfree(crypt); ++#ifdef _RTL8187_EXT_PATCH_ ++ ieee->cryptlist[j]->crypt[i] = NULL; ++ //kfree(ieee->cryptlist[j]); ++ //ieee->cryptlist[j] = NULL; ++#else ++ ieee->crypt[i] = NULL; ++#endif ++ } ++#ifdef _RTL8187_EXT_PATCH_ ++ } ++ } ++#endif ++} ++#ifdef _RTL8187_EXT_PATCH_ ++for(j=0;jcryptlist[j]) ++ { ++ kfree(ieee->cryptlist[j]); ++ ieee->cryptlist[j] = NULL; ++ } ++ } ++ ++ for (i = 0; i < IEEE_MESH_MAC_HASH_SIZE; i++) { ++ list_for_each_safe(p, q, &ieee->mesh_mac_hash[i]) { ++ kfree(list_entry(p, struct ieee_mesh_seq, list)); ++ list_del(p); ++ } ++ } ++#endif ++ ieee80211_networks_free(ieee); ++ ++ for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) { ++ list_for_each_safe(p, q, &ieee->ibss_mac_hash[i]) { ++ kfree(list_entry(p, struct ieee_ibss_seq, list)); ++ list_del(p); ++ } ++ } ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) ++ free_netdev(dev); ++#else ++ kfree(dev); ++#endif ++} ++ ++#ifdef CONFIG_IEEE80211_DEBUG ++ ++static int debug = 0; ++u32 ieee80211_debug_level = 0; ++struct proc_dir_entry *ieee80211_proc = NULL; ++ ++static int show_debug_level(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ return snprintf(page, count, "0x%08X\n", ieee80211_debug_level); ++} ++ ++static int store_debug_level(struct file *file, const char *buffer, ++ unsigned long count, void *data) ++{ ++ char buf[] = "0x00000000"; ++ unsigned long len = min(sizeof(buf) - 1, (u32)count); ++ char *p = (char *)buf; ++ unsigned long val; ++ ++ if (copy_from_user(buf, buffer, len)) ++ return count; ++ buf[len] = 0; ++ if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { ++ p++; ++ if (p[0] == 'x' || p[0] == 'X') ++ p++; ++ val = simple_strtoul(p, &p, 16); ++ } else ++ val = simple_strtoul(p, &p, 10); ++ if (p == buf) ++ printk(KERN_INFO DRV_NAME ++ ": %s is not in hex or decimal form.\n", buf); ++ else ++ ieee80211_debug_level = val; ++ ++ return strnlen(buf, count); ++} ++ ++static int __init ieee80211_init(void) ++{ ++ struct proc_dir_entry *e; ++ ++ ieee80211_debug_level = debug; ++ ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net); ++ if (ieee80211_proc == NULL) { ++ IEEE80211_ERROR("Unable to create " DRV_NAME ++ " proc directory\n"); ++ return -EIO; ++ } ++ e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR, ++ ieee80211_proc); ++ if (!e) { ++ remove_proc_entry(DRV_NAME, proc_net); ++ ieee80211_proc = NULL; ++ return -EIO; ++ } ++ e->read_proc = show_debug_level; ++ e->write_proc = store_debug_level; ++ e->data = NULL; ++ ++ return 0; ++} ++ ++static void __exit ieee80211_exit(void) ++{ ++ if (ieee80211_proc) { ++ remove_proc_entry("debug_level", ieee80211_proc); ++ remove_proc_entry(DRV_NAME, proc_net); ++ ieee80211_proc = NULL; ++ } ++} ++ ++#include ++module_param(debug, int, 0444); ++MODULE_PARM_DESC(debug, "debug output mask"); ++ ++ ++module_exit(ieee80211_exit); ++module_init(ieee80211_init); ++#endif ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++EXPORT_SYMBOL(alloc_ieee80211); ++EXPORT_SYMBOL(free_ieee80211); ++#else ++EXPORT_SYMBOL_NOVERS(alloc_ieee80211); ++EXPORT_SYMBOL_NOVERS(free_ieee80211); ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_rx.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_rx.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_rx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_rx.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,2074 @@ ++/* ++ * Original code based Host AP (software wireless LAN access point) driver ++ * for Intersil Prism2/2.5/3 - hostap.o module, common routines ++ * ++ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen ++ * ++ * Copyright (c) 2002-2003, Jouni Malinen ++ * Copyright (c) 2004, Intel Corporation ++ * ++ * 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. See README and COPYING for ++ * more details. ++ ****************************************************************************** ++ ++ Few modifications for Realtek's Wi-Fi drivers by ++ Andrea Merello ++ ++ A special thanks goes to Realtek for their support ! ++ ++******************************************************************************/ ++ ++ ++#include ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ieee80211.h" ++#ifdef ENABLE_DOT11D ++#include "dot11d.h" ++#endif ++ ++static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee, ++ struct sk_buff *skb, ++ struct ieee80211_rx_stats *rx_stats) ++{ ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ u16 fc = le16_to_cpu(hdr->frame_ctl); ++ ++ skb->dev = ieee->dev; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) ++ skb_reset_mac_header(skb); ++#else ++ skb->mac.raw = skb->data; ++#endif ++ ++ //skb->mac.raw = skb->data; ++ skb_pull(skb, ieee80211_get_hdrlen(fc)); ++ skb->pkt_type = PACKET_OTHERHOST; ++ skb->protocol = __constant_htons(ETH_P_80211_RAW); ++ memset(skb->cb, 0, sizeof(skb->cb)); ++ netif_rx(skb); ++} ++ ++ ++/* Called only as a tasklet (software IRQ) */ ++static struct ieee80211_frag_entry * ++ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq, ++ unsigned int frag, u8 tid,u8 *src, u8 *dst) ++{ ++ struct ieee80211_frag_entry *entry; ++ int i; ++ ++ for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) { ++ entry = &ieee->frag_cache[tid][i]; ++ if (entry->skb != NULL && ++ time_after(jiffies, entry->first_frag_time + 2 * HZ)) { ++ IEEE80211_DEBUG_FRAG( ++ "expiring fragment cache entry " ++ "seq=%u last_frag=%u\n", ++ entry->seq, entry->last_frag); ++ dev_kfree_skb_any(entry->skb); ++ entry->skb = NULL; ++ } ++ ++ if (entry->skb != NULL && entry->seq == seq && ++ (entry->last_frag + 1 == frag || frag == -1) && ++ memcmp(entry->src_addr, src, ETH_ALEN) == 0 && ++ memcmp(entry->dst_addr, dst, ETH_ALEN) == 0) ++ return entry; ++ } ++ ++ return NULL; ++} ++ ++/* Called only as a tasklet (software IRQ) */ ++static struct sk_buff * ++ieee80211_frag_cache_get(struct ieee80211_device *ieee, ++ struct ieee80211_hdr *hdr) ++{ ++ struct sk_buff *skb = NULL; ++ u16 fc = le16_to_cpu(hdr->frame_ctl); ++ u16 sc = le16_to_cpu(hdr->seq_ctl); ++ unsigned int frag = WLAN_GET_SEQ_FRAG(sc); ++ unsigned int seq = WLAN_GET_SEQ_SEQ(sc); ++ struct ieee80211_frag_entry *entry; ++ struct ieee80211_hdr_3addr_QOS *hdr_3addr_QoS; ++ struct ieee80211_hdr_QOS *hdr_4addr_QoS; ++ u8 tid; ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(ieee->iw_mode == ieee->iw_ext_mode) ++ { ++ tid = (hdr->addr2[ETH_ALEN-2] ^ hdr->addr2[ETH_ALEN-1]) & IEEE80211_QOS_TID; ++ } ++ else ++#endif ++ if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) { ++ hdr_4addr_QoS = (struct ieee80211_hdr_QOS *)hdr; ++ tid = le16_to_cpu(hdr_4addr_QoS->QOS_ctl) & IEEE80211_QOS_TID; ++ tid = UP2AC(tid); ++ tid ++; ++ } else if (IEEE80211_QOS_HAS_SEQ(fc)) { ++ hdr_3addr_QoS = (struct ieee80211_hdr_3addr_QOS *)hdr; ++ tid = le16_to_cpu(hdr_3addr_QoS->QOS_ctl) & IEEE80211_QOS_TID; ++ tid = UP2AC(tid); ++ tid ++; ++ } else { ++ tid = 0; ++ } ++ ++ if (frag == 0) { ++ /* Reserve enough space to fit maximum frame length */ ++ skb = dev_alloc_skb(ieee->dev->mtu + ++ sizeof(struct ieee80211_hdr) + ++ 8 /* LLC */ + ++ 2 /* alignment */ + ++ 8 /* WEP */ + ++ ETH_ALEN /* WDS */ + ++ (IEEE80211_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */); ++ if (skb == NULL) ++ return NULL; ++ ++ entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]]; ++ ieee->frag_next_idx[tid]++; ++ if (ieee->frag_next_idx[tid] >= IEEE80211_FRAG_CACHE_LEN) ++ ieee->frag_next_idx[tid] = 0; ++ ++ if (entry->skb != NULL) ++ dev_kfree_skb_any(entry->skb); ++ ++ entry->first_frag_time = jiffies; ++ entry->seq = seq; ++ entry->last_frag = frag; ++ entry->skb = skb; ++ memcpy(entry->src_addr, hdr->addr2, ETH_ALEN); ++ memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN); ++ } else { ++ /* received a fragment of a frame for which the head fragment ++ * should have already been received */ ++ entry = ieee80211_frag_cache_find(ieee, seq, frag, tid,hdr->addr2, ++ hdr->addr1); ++ if (entry != NULL) { ++ entry->last_frag = frag; ++ skb = entry->skb; ++ } ++ } ++ ++ return skb; ++} ++ ++ ++/* Called only as a tasklet (software IRQ) */ ++static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, ++ struct ieee80211_hdr *hdr) ++{ ++ u16 fc = le16_to_cpu(hdr->frame_ctl); ++ u16 sc = le16_to_cpu(hdr->seq_ctl); ++ unsigned int seq = WLAN_GET_SEQ_SEQ(sc); ++ struct ieee80211_frag_entry *entry; ++ struct ieee80211_hdr_3addr_QOS *hdr_3addr_QoS; ++ struct ieee80211_hdr_QOS *hdr_4addr_QoS; ++ u8 tid; ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(ieee->iw_mode == ieee->iw_ext_mode) ++ { ++ tid = (hdr->addr2[ETH_ALEN-2] ^ hdr->addr2[ETH_ALEN-1]) & IEEE80211_QOS_TID; ++ } ++ else ++#endif ++ if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) { ++ hdr_4addr_QoS = (struct ieee80211_hdr_QOS *)hdr; ++ tid = le16_to_cpu(hdr_4addr_QoS->QOS_ctl) & IEEE80211_QOS_TID; ++ tid = UP2AC(tid); ++ tid ++; ++ } else if (IEEE80211_QOS_HAS_SEQ(fc)) { ++ hdr_3addr_QoS = (struct ieee80211_hdr_3addr_QOS *)hdr; ++ tid = le16_to_cpu(hdr_3addr_QoS->QOS_ctl) & IEEE80211_QOS_TID; ++ tid = UP2AC(tid); ++ tid ++; ++ } else { ++ tid = 0; ++ } ++ ++ entry = ieee80211_frag_cache_find(ieee, seq, -1, tid,hdr->addr2, ++ hdr->addr1); ++ ++ if (entry == NULL) { ++ IEEE80211_DEBUG_FRAG( ++ "could not invalidate fragment cache " ++ "entry (seq=%u)\n", seq); ++ return -1; ++ } ++ ++ entry->skb = NULL; ++ return 0; ++} ++ ++ ++ ++/* ieee80211_rx_frame_mgtmt ++ * ++ * Responsible for handling management control frames ++ * ++ * Called by ieee80211_rx */ ++static inline int ++ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, ++ struct ieee80211_rx_stats *rx_stats, u16 type, ++ u16 stype) ++{ ++ /* On the struct stats definition there is written that ++ * this is not mandatory.... but seems that the probe ++ * response parser uses it ++ */ ++ struct ieee80211_hdr * hdr = (struct ieee80211_hdr*)skb->data; ++ rx_stats->len = skb->len; ++ ieee80211_rx_mgt(ieee,(struct ieee80211_hdr *)skb->data,rx_stats); ++ ++ if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) ++ { ++ dev_kfree_skb_any(skb); ++ return 0; ++ } ++ ++ ieee80211_rx_frame_softmac(ieee, skb, rx_stats, type, stype); ++ ++ dev_kfree_skb_any(skb); ++ ++ return 0; ++ ++ #ifdef NOT_YET ++ if (ieee->iw_mode == IW_MODE_MASTER) { ++ printk(KERN_DEBUG "%s: Master mode not yet suppported.\n", ++ ieee->dev->name); ++ return 0; ++/* ++ hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr *) ++ skb->data);*/ ++ } ++ ++ if (ieee->hostapd && type == IEEE80211_TYPE_MGMT) { ++ if (stype == WLAN_FC_STYPE_BEACON && ++ ieee->iw_mode == IW_MODE_MASTER) { ++ struct sk_buff *skb2; ++ /* Process beacon frames also in kernel driver to ++ * update STA(AP) table statistics */ ++ skb2 = skb_clone(skb, GFP_ATOMIC); ++ if (skb2) ++ hostap_rx(skb2->dev, skb2, rx_stats); ++ } ++ ++ /* send management frames to the user space daemon for ++ * processing */ ++ ieee->apdevstats.rx_packets++; ++ ieee->apdevstats.rx_bytes += skb->len; ++ prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT); ++ return 0; ++ } ++ ++ if (ieee->iw_mode == IW_MODE_MASTER) { ++ if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) { ++ printk(KERN_DEBUG "%s: unknown management frame " ++ "(type=0x%02x, stype=0x%02x) dropped\n", ++ skb->dev->name, type, stype); ++ return -1; ++ } ++ ++ hostap_rx(skb->dev, skb, rx_stats); ++ return 0; ++ } ++ ++ printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame " ++ "received in non-Host AP mode\n", skb->dev->name); ++ return -1; ++ #endif ++} ++ ++ ++ ++/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ ++/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ ++static unsigned char rfc1042_header[] = ++{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; ++/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ ++static unsigned char bridge_tunnel_header[] = ++{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; ++/* No encapsulation header if EtherType < 0x600 (=length) */ ++ ++/* Called by ieee80211_rx_frame_decrypt */ ++static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee, ++ struct sk_buff *skb, size_t hdrlen) ++{ ++ struct net_device *dev = ieee->dev; ++ u16 fc, ethertype; ++ struct ieee80211_hdr *hdr; ++ u8 *pos; ++ ++ if (skb->len < 24) ++ return 0; ++ ++ hdr = (struct ieee80211_hdr *) skb->data; ++ fc = le16_to_cpu(hdr->frame_ctl); ++ ++ /* check that the frame is unicast frame to us */ ++ if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == ++ IEEE80211_FCTL_TODS && ++ memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 && ++ memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) { ++ /* ToDS frame with own addr BSSID and DA */ ++ } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == ++ IEEE80211_FCTL_FROMDS && ++ memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) { ++ /* FromDS frame with own addr as DA */ ++ } else ++ return 0; ++ ++ if (skb->len < 24 + 8) ++ return 0; ++ ++ /* check for port access entity Ethernet type */ ++// pos = skb->data + 24; ++ pos = skb->data + hdrlen; ++ ethertype = (pos[6] << 8) | pos[7]; ++ if (ethertype == ETH_P_PAE) ++ return 1; ++ ++ return 0; ++} ++ ++/* Called only as a tasklet (software IRQ), by ieee80211_rx */ ++static inline int ++ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb, ++ struct ieee80211_crypt_data *crypt) ++{ ++ struct ieee80211_hdr *hdr; ++ int res, hdrlen; ++ ++ if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL) ++ return 0; ++ ++ hdr = (struct ieee80211_hdr *) skb->data; ++#ifdef _RTL8187_EXT_PATCH_ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && (ieee->ext_patch_ieee80211_rx_frame_get_hdrlen)) ++ { ++ hdrlen = ieee->ext_patch_ieee80211_rx_frame_get_hdrlen(ieee, skb); ++ } ++ else ++#endif ++ hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); ++ ++#ifdef CONFIG_IEEE80211_CRYPT_TKIP ++ if (ieee->tkip_countermeasures && ++ strcmp(crypt->ops->name, "TKIP") == 0) { ++ if (net_ratelimit()) { ++ printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " ++ "received packet from " MAC_FMT "\n", ++ ieee->dev->name, MAC_ARG(hdr->addr2)); ++ } ++ return -1; ++ } ++#endif ++ ++ atomic_inc(&crypt->refcnt); ++ res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv); ++ atomic_dec(&crypt->refcnt); ++ if (res < 0) { ++ IEEE80211_DEBUG_DROP( ++ "decryption failed (SA=" MAC_FMT ++ ") res=%d\n", MAC_ARG(hdr->addr2), res); ++ if (res == -2) ++ IEEE80211_DEBUG_DROP("Decryption failed ICV " ++ "mismatch (key %d)\n", ++ skb->data[hdrlen + 3] >> 6); ++ ieee->ieee_stats.rx_discards_undecryptable++; ++ return -1; ++ } ++ ++ return res; ++} ++ ++ ++/* Called only as a tasklet (software IRQ), by ieee80211_rx */ ++static inline int ++ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *skb, ++ int keyidx, struct ieee80211_crypt_data *crypt) ++{ ++ struct ieee80211_hdr *hdr; ++ int res, hdrlen; ++ ++ if (crypt == NULL || crypt->ops->decrypt_msdu == NULL) ++ return 0; ++ ++ hdr = (struct ieee80211_hdr *) skb->data; ++#ifdef _RTL8187_EXT_PATCH_ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && (ieee->ext_patch_ieee80211_rx_frame_get_hdrlen)) ++ { ++ hdrlen = ieee->ext_patch_ieee80211_rx_frame_get_hdrlen(ieee, skb); ++ } ++ else ++#endif ++ hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); ++ ++ atomic_inc(&crypt->refcnt); ++ res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv); ++ atomic_dec(&crypt->refcnt); ++ if (res < 0) { ++ printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed" ++ " (SA=" MAC_FMT " keyidx=%d)\n", ++ ieee->dev->name, MAC_ARG(hdr->addr2), keyidx); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++ ++/* this function is stolen from ipw2200 driver*/ ++#define IEEE_PACKET_RETRY_TIME (5*HZ) ++static int is_duplicate_packet(struct ieee80211_device *ieee, ++ struct ieee80211_hdr *header) ++{ ++ u16 fc = le16_to_cpu(header->frame_ctl); ++ u16 sc = le16_to_cpu(header->seq_ctl); ++ u16 seq = WLAN_GET_SEQ_SEQ(sc); ++ u16 frag = WLAN_GET_SEQ_FRAG(sc); ++ u16 *last_seq, *last_frag; ++ unsigned long *last_time; ++ struct ieee80211_hdr_3addr_QOS *hdr_3addr_QoS; ++ struct ieee80211_hdr_QOS *hdr_4addr_QoS; ++ u8 tid; ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(ieee->iw_mode == ieee->iw_ext_mode) ++ { ++ tid = (header->addr2[ETH_ALEN-2] ^ header->addr2[ETH_ALEN-1]) & IEEE80211_QOS_TID; ++ } ++ else ++#endif ++ //TO2DS and QoS ++ if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) { ++ hdr_4addr_QoS = (struct ieee80211_hdr_QOS *)header; ++ tid = le16_to_cpu(hdr_4addr_QoS->QOS_ctl) & IEEE80211_QOS_TID; ++ tid = UP2AC(tid); ++ tid ++; ++ } else if(IEEE80211_QOS_HAS_SEQ(fc)) { //QoS ++ hdr_3addr_QoS = (struct ieee80211_hdr_3addr_QOS*)header; ++ tid = le16_to_cpu(hdr_3addr_QoS->QOS_ctl) & IEEE80211_QOS_TID; ++ tid = UP2AC(tid); ++ tid ++; ++ } else { // no QoS ++ tid = 0; ++ } ++ ++ switch (ieee->iw_mode) { ++ case IW_MODE_ADHOC: ++ { ++ struct list_head *p; ++ struct ieee_ibss_seq *entry = NULL; ++ u8 *mac = header->addr2; ++ int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE; ++ //for (pos = (head)->next; pos != (head); pos = pos->next) ++ __list_for_each(p, &ieee->ibss_mac_hash[index]) { ++ entry = list_entry(p, struct ieee_ibss_seq, list); ++ if (!memcmp(entry->mac, mac, ETH_ALEN)) ++ break; ++ } ++ // if (memcmp(entry->mac, mac, ETH_ALEN)){ ++ if (p == &ieee->ibss_mac_hash[index]) { ++ entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC); ++ if (!entry) { ++ printk(KERN_WARNING "Cannot malloc new mac entry\n"); ++ return 0; ++ } ++ memcpy(entry->mac, mac, ETH_ALEN); ++ entry->seq_num[tid] = seq; ++ entry->frag_num[tid] = frag; ++ entry->packet_time[tid] = jiffies; ++ list_add(&entry->list, &ieee->ibss_mac_hash[index]); ++ return 0; ++ } ++ last_seq = &entry->seq_num[tid]; ++ last_frag = &entry->frag_num[tid]; ++ last_time = &entry->packet_time[tid]; ++ break; ++ } ++ ++ case IW_MODE_INFRA: ++ last_seq = &ieee->last_rxseq_num[tid]; ++ last_frag = &ieee->last_rxfrag_num[tid]; ++ last_time = &ieee->last_packet_time[tid]; ++ ++ break; ++ default: ++#ifdef _RTL8187_EXT_PATCH_ ++ if(ieee->iw_mode == ieee->iw_ext_mode) ++ { ++#if 0 ++ printk("==============> tid = %d\n", tid); ++ last_seq = &ieee->last_rxseq_num[tid]; ++ last_frag = &ieee->last_rxfrag_num[tid]; ++ last_time = &ieee->last_packet_time[tid]; ++#else ++ struct list_head *p; ++ struct ieee_mesh_seq *entry = NULL; ++ u8 *mac = header->addr2; ++ int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE; ++ ++ __list_for_each(p, &ieee->mesh_mac_hash[index]) { ++ entry = list_entry(p, struct ieee_mesh_seq, list); ++ if (!memcmp(entry->mac, mac, ETH_ALEN)) ++ break; ++ } ++ if (p == &ieee->mesh_mac_hash[index]) { ++ entry = kmalloc(sizeof(struct ieee_mesh_seq), GFP_ATOMIC); ++ if (!entry) { ++ printk(KERN_WARNING "Cannot malloc new mac entry for mesh\n"); ++ return 0; ++ } ++ memcpy(entry->mac, mac, ETH_ALEN); ++ entry->seq_num = seq; ++ entry->frag_num = frag; ++ entry->packet_time = jiffies; ++ list_add(&entry->list, &ieee->mesh_mac_hash[index]); ++ return 0; ++ } ++ last_seq = &entry->seq_num; ++ last_frag = &entry->frag_num; ++ last_time = &entry->packet_time; ++#endif ++ break; ++ } ++ else ++#endif ++ return 0; ++ } ++ ++// if(tid != 0) { ++// printk(KERN_WARNING ":)))))))))))%x %x %x, fc(%x)\n", tid, *last_seq, seq, header->frame_ctl); ++// } ++ if ((*last_seq == seq) && ++ time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) { ++ if (*last_frag == frag){ ++ //printk(KERN_WARNING "[1] go drop!\n"); ++ goto drop; ++ ++ } ++ if (*last_frag + 1 != frag) ++ /* out-of-order fragment */ ++ //printk(KERN_WARNING "[2] go drop!\n"); ++ goto drop; ++ } else ++ *last_seq = seq; ++ ++ *last_frag = frag; ++ *last_time = jiffies; ++ return 0; ++ ++drop: ++// BUG_ON(!(fc & IEEE80211_FCTL_RETRY)); ++// printk("DUP\n"); ++ ++ return 1; ++} ++#ifdef JUST_FOR_87SEMESH ++#define ActionHeadLen 30 ++#define WIFI_MESH_TYPE IEEE80211_FTYPE_DATA ++#define WIFI_11S_MESH_ACTION 0x00A0 ++#endif ++ ++/* All received frames are sent to this function. @skb contains the frame in ++ * IEEE 802.11 format, i.e., in the format it was sent over air. ++ * This function is called only as a tasklet (software IRQ). */ ++int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, ++ struct ieee80211_rx_stats *rx_stats) ++{ ++ struct net_device *dev = ieee->dev; ++ struct ieee80211_hdr *hdr; ++ //struct ieee80211_hdr_3addr_QOS *hdr; ++ ++ size_t hdrlen; ++ u16 fc, type, stype, sc; ++ struct net_device_stats *stats; ++ unsigned int frag; ++ u8 *payload; ++ u16 ethertype; ++#ifdef NOT_YET ++ struct net_device *wds = NULL; ++ struct sk_buff *skb2 = NULL; ++ struct net_device *wds = NULL; ++ int frame_authorized = 0; ++ int from_assoc_ap = 0; ++ void *sta = NULL; ++#endif ++// u16 QOS_ctl = 0; ++ u8 dst[ETH_ALEN]; ++ u8 src[ETH_ALEN]; ++ u8 bssid[ETH_ALEN]; ++ struct ieee80211_crypt_data *crypt = NULL; ++ int keyidx = 0; ++ ++ //Added for mesh by Lawrence. ++ //u8 status; ++ //u32 flags; ++ ++ // cheat the the hdr type ++ hdr = (struct ieee80211_hdr *)skb->data; ++ stats = &ieee->stats; ++ ++ if (skb->len < 10) { ++ printk(KERN_INFO "%s: SKB length < 10\n", ++ dev->name); ++ goto rx_dropped; ++ } ++#if 0 ++//{added by david for filter the packet listed in the filter table ++#ifdef _RTL8187_EXT_PATCH_ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && (ieee->ext_patch_ieee80211_acl_query)) ++ { ++ if(!ieee->ext_patch_ieee80211_acl_query(ieee, hdr->addr2)) ++ goto rx_dropped; ++ } ++#endif ++//} ++#endif ++ fc = le16_to_cpu(hdr->frame_ctl); ++ type = WLAN_FC_GET_TYPE(fc); ++ stype = WLAN_FC_GET_STYPE(fc); ++ ++ //Because 87se's bad feature,do more handle. ++#ifdef JUST_FOR_87SEMESH ++ ++u8 tmphead[ActionHeadLen]; ++ if(type ==WIFI_MESH_TYPE && stype== WIFI_11S_MESH_ACTION ) ++ //head=sizeof(struct ieee80211_hdr)=30 ++ { ++ memset(tmphead,0,ActionHeadLen); ++ memcpy(tmphead,skb->data,ActionHeadLen); ++ ++ skb_pull(skb,ActionHeadLen+2); ++ memcpy(skb_push(skb,ActionHeadLen),tmphead,ActionHeadLen); ++ hdr = (struct ieee80211_hdr *)skb->data; ++ } ++ ++#endif ++ sc = le16_to_cpu(hdr->seq_ctl); ++ ++ frag = WLAN_GET_SEQ_FRAG(sc); ++#ifdef _RTL8187_EXT_PATCH_ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && (ieee->ext_patch_ieee80211_rx_frame_get_hdrlen)) ++ { ++ hdrlen = ieee->ext_patch_ieee80211_rx_frame_get_hdrlen(ieee, skb); ++ if(skb->len < hdrlen) ++ goto rx_dropped; ++ } ++ else ++#endif ++ hdrlen = ieee80211_get_hdrlen(fc); ++ ++#ifdef NOT_YET ++#if WIRELESS_EXT > 15 ++ /* Put this code here so that we avoid duplicating it in all ++ * Rx paths. - Jean II */ ++#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ ++ /* If spy monitoring on */ ++ if (iface->spy_data.spy_number > 0) { ++ struct iw_quality wstats; ++ wstats.level = rx_stats->signal; ++ wstats.noise = rx_stats->noise; ++ wstats.updated = 6; /* No qual value */ ++ /* Update spy records */ ++ wireless_spy_update(dev, hdr->addr2, &wstats); ++ } ++#endif /* IW_WIRELESS_SPY */ ++#endif /* WIRELESS_EXT > 15 */ ++ hostap_update_rx_stats(local->ap, hdr, rx_stats); ++#endif ++ ++#if WIRELESS_EXT > 15 ++ if (ieee->iw_mode == IW_MODE_MONITOR) { ++ ieee80211_monitor_rx(ieee, skb, rx_stats); ++ stats->rx_packets++; ++ stats->rx_bytes += skb->len; ++ return 1; ++ } ++#endif ++ if (ieee->host_decrypt) { ++ int idx = 0; ++ if (skb->len >= hdrlen + 3) ++ idx = skb->data[hdrlen + 3] >> 6; ++#ifdef _RTL8187_EXT_PATCH_ ++ ++ crypt = ieee->cryptlist[0]->crypt[idx]; ++#if 0 ++ { ++ int i = ieee80211_find_MP(ieee, ((struct ieee80211_hdr*)skb->data)->addr2); ++ if (i == -1) ++ { ++ printk("error find entry in entry list\n"); ++ goto rx_dropped; ++ } ++ //printk("%s():"MAC_FMT", find in index:%d", __FUNCTION__, MAC_ARG(((struct ieee80211_hdr*)skb->data)->addr2), i); ++ crypt = ieee->cryptlist[i]->crypt[idx]; ++ } ++#endif ++#else ++ crypt = ieee->crypt[idx]; ++#endif ++ ++#ifdef NOT_YET ++ sta = NULL; ++ ++ /* Use station specific key to override default keys if the ++ * receiver address is a unicast address ("individual RA"). If ++ * bcrx_sta_key parameter is set, station specific key is used ++ * even with broad/multicast targets (this is against IEEE ++ * 802.11, but makes it easier to use different keys with ++ * stations that do not support WEP key mapping). */ ++ ++ if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) ++ (void) hostap_handle_sta_crypto(local, hdr, &crypt, ++ &sta); ++#endif ++ ++ /* allow NULL decrypt to indicate an station specific override ++ * for default encryption */ ++ if (crypt && (crypt->ops == NULL || ++ crypt->ops->decrypt_mpdu == NULL)) ++ crypt = NULL; ++ ++ if (!crypt && (fc & IEEE80211_FCTL_WEP)) { ++ /* This seems to be triggered by some (multicast?) ++ * frames from other than current BSS, so just drop the ++ * frames silently instead of filling system log with ++ * these reports. */ ++ IEEE80211_DEBUG_DROP("Decryption failed (not set)" ++ " (SA=" MAC_FMT ")\n", ++ MAC_ARG(hdr->addr2)); ++ ieee->ieee_stats.rx_discards_undecryptable++; ++ goto rx_dropped; ++ } ++ } ++ ++ if (skb->len < IEEE80211_DATA_HDR3_LEN) ++ goto rx_dropped; ++ ++ // if QoS enabled, should check the sequence for each of the AC ++ if (is_duplicate_packet(ieee, hdr)) ++ goto rx_dropped; ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if( ieee->iw_mode == ieee->iw_ext_mode && ieee->ext_patch_ieee80211_rx_mgt_update_expire ) ++ ieee->ext_patch_ieee80211_rx_mgt_update_expire( ieee, skb ); ++#endif ++ ++ if (type == IEEE80211_FTYPE_MGMT) { ++ ++ #if 0 ++ if ( stype == IEEE80211_STYPE_AUTH && ++ fc & IEEE80211_FCTL_WEP && ieee->host_decrypt && ++ (keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0) ++ { ++ printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth " ++ "from " MAC_FMT "\n", dev->name, ++ MAC_ARG(hdr->addr2)); ++ /* TODO: could inform hostapd about this so that it ++ * could send auth failure report */ ++ goto rx_dropped; ++ } ++ #endif ++ ++ ++ if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype)) ++ goto rx_dropped; ++ else ++ goto rx_exit; ++ } ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_rx_on_rx) ++ { ++ if(ieee->ext_patch_ieee80211_rx_on_rx(ieee, skb, rx_stats, type, stype)==0) ++ { ++ goto rx_exit; ++ } ++ } ++#endif ++ ++ /* Data frame - extract src/dst addresses */ ++ switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { ++ case IEEE80211_FCTL_FROMDS: ++ memcpy(dst, hdr->addr1, ETH_ALEN); ++ memcpy(src, hdr->addr3, ETH_ALEN); ++ memcpy(bssid, hdr->addr2, ETH_ALEN); ++ break; ++ case IEEE80211_FCTL_TODS: ++ memcpy(dst, hdr->addr3, ETH_ALEN); ++ memcpy(src, hdr->addr2, ETH_ALEN); ++ memcpy(bssid, hdr->addr1, ETH_ALEN); ++ break; ++ case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: ++ if (skb->len < IEEE80211_DATA_HDR4_LEN) ++ goto rx_dropped; ++ memcpy(dst, hdr->addr3, ETH_ALEN); ++ memcpy(src, hdr->addr4, ETH_ALEN); ++ memcpy(bssid, ieee->current_network.bssid, ETH_ALEN); ++ break; ++ case 0: ++ memcpy(dst, hdr->addr1, ETH_ALEN); ++ memcpy(src, hdr->addr2, ETH_ALEN); ++ memcpy(bssid, hdr->addr3, ETH_ALEN); ++ break; ++ } ++ ++#ifdef NOT_YET ++ if (hostap_rx_frame_wds(ieee, hdr, fc, &wds)) ++ goto rx_dropped; ++ if (wds) { ++ skb->dev = dev = wds; ++ stats = hostap_get_stats(dev); ++ } ++ ++ if (ieee->iw_mode == IW_MODE_MASTER && !wds && ++ (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS && ++ ieee->stadev && ++ memcmp(hdr->addr2, ieee->assoc_ap_addr, ETH_ALEN) == 0) { ++ /* Frame from BSSID of the AP for which we are a client */ ++ skb->dev = dev = ieee->stadev; ++ stats = hostap_get_stats(dev); ++ from_assoc_ap = 1; ++ } ++#endif ++ ++ dev->last_rx = jiffies; ++ ++#ifdef NOT_YET ++ if ((ieee->iw_mode == IW_MODE_MASTER || ++ ieee->iw_mode == IW_MODE_REPEAT) && ++ !from_assoc_ap) { ++ switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats, ++ wds != NULL)) { ++ case AP_RX_CONTINUE_NOT_AUTHORIZED: ++ frame_authorized = 0; ++ break; ++ case AP_RX_CONTINUE: ++ frame_authorized = 1; ++ break; ++ case AP_RX_DROP: ++ goto rx_dropped; ++ case AP_RX_EXIT: ++ goto rx_exit; ++ } ++ } ++#endif ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_rx_is_valid_framectl) ++ { ++ if(ieee->ext_patch_ieee80211_rx_is_valid_framectl(ieee, fc, type, stype)==0) ++ goto rx_dropped; ++ } ++ else ++#endif ++ /* Nullfunc frames may have PS-bit set, so they must be passed to ++ * hostap_handle_sta_rx() before being dropped here. */ ++ if (stype != IEEE80211_STYPE_DATA && ++ stype != IEEE80211_STYPE_DATA_CFACK && ++ stype != IEEE80211_STYPE_DATA_CFPOLL && ++ stype != IEEE80211_STYPE_DATA_CFACKPOLL&& ++ stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4 ++ ) { ++ if (stype != IEEE80211_STYPE_NULLFUNC) ++ IEEE80211_DEBUG_DROP( ++ "RX: dropped data frame " ++ "with no data (type=0x%02x, " ++ "subtype=0x%02x, len=%d)\n", ++ type, stype, skb->len); ++ goto rx_dropped; ++ } ++ ++ if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN)) ++ goto rx_dropped; ++ ++ /* skb: hdr + (possibly fragmented, possibly encrypted) payload */ ++#ifdef _RTL8187_EXT_PATCH_ ++ if (ieee->host_decrypt && crypt) { ++ int idx = 0; ++ if (skb->len >= hdrlen + 3) ++ idx = skb->data[hdrlen + 3] >> 6; ++ if (ieee->iw_ext_mode == ieee->iw_mode) //if in mesh mode ++ { ++ int i = ieee80211_find_MP(ieee, ((struct ieee80211_hdr*)skb->data)->addr2, 0); ++ if (i == -1) ++ { ++ printk("error find entry in entry list\n"); ++ goto rx_dropped; ++ } ++ // printk("%s():"MAC_FMT", find in index:%d\n", __FUNCTION__, MAC_ARG(((struct ieee80211_hdr*)skb->data)->addr2), i); ++ if (ieee->cryptlist[i]&&ieee->cryptlist[i]->crypt[idx]) ++ crypt = ieee->cryptlist[i]->crypt[idx]; ++ ++ else ++ crypt = NULL; ++ } ++ else ++ crypt = ieee->cryptlist[0]->crypt[idx]; ++ } ++#endif ++ ++ if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && ++ (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) ++ goto rx_dropped; ++ ++ hdr = (struct ieee80211_hdr *) skb->data; ++ ++ /* skb: hdr + (possibly fragmented) plaintext payload */ ++ // PR: FIXME: hostap has additional conditions in the "if" below: ++ // ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && ++ if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) { ++ int flen; ++ struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr); ++ IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag); ++ ++ if (!frag_skb) { ++ IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG, ++ "Rx cannot get skb from fragment " ++ "cache (morefrag=%d seq=%u frag=%u)\n", ++ (fc & IEEE80211_FCTL_MOREFRAGS) != 0, ++ WLAN_GET_SEQ_SEQ(sc), frag); ++ goto rx_dropped; ++ } ++ flen = skb->len; ++ if (frag != 0) ++ flen -= hdrlen; ++ ++ if (frag_skb->tail + flen > frag_skb->end) { ++ printk(KERN_WARNING "%s: host decrypted and " ++ "reassembled frame did not fit skb\n", ++ dev->name); ++ ieee80211_frag_cache_invalidate(ieee, hdr); ++ goto rx_dropped; ++ } ++ ++ if (frag == 0) { ++ /* copy first fragment (including full headers) into ++ * beginning of the fragment cache skb */ ++ memcpy(skb_put(frag_skb, flen), skb->data, flen); ++ } else { ++ /* append frame payload to the end of the fragment ++ * cache skb */ ++ memcpy(skb_put(frag_skb, flen), skb->data + hdrlen, ++ flen); ++ } ++ dev_kfree_skb_any(skb); ++ skb = NULL; ++ ++ if (fc & IEEE80211_FCTL_MOREFRAGS) { ++ /* more fragments expected - leave the skb in fragment ++ * cache for now; it will be delivered to upper layers ++ * after all fragments have been received */ ++ goto rx_exit; ++ } ++ ++ /* this was the last fragment and the frame will be ++ * delivered, so remove skb from fragment cache */ ++ skb = frag_skb; ++ hdr = (struct ieee80211_hdr *) skb->data; ++ ieee80211_frag_cache_invalidate(ieee, hdr); ++ } ++ ++ /* skb: hdr + (possible reassembled) full MSDU payload; possibly still ++ * encrypted/authenticated */ ++ if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && ++ ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) ++ goto rx_dropped; ++ ++ hdr = (struct ieee80211_hdr *) skb->data; ++ if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) { ++ if (/*ieee->ieee802_1x &&*/ ++ ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { ++ ++#ifdef CONFIG_IEEE80211_DEBUG ++ /* pass unencrypted EAPOL frames even if encryption is ++ * configured */ ++ struct eapol *eap = (struct eapol *)(skb->data + ++ 24); ++ IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", ++ eap_get_type(eap->type)); ++#endif ++ } else { ++ IEEE80211_DEBUG_DROP( ++ "encryption configured, but RX " ++ "frame not encrypted (SA=" MAC_FMT ")\n", ++ MAC_ARG(hdr->addr2)); ++ goto rx_dropped; ++ } ++ } ++ ++#ifdef CONFIG_IEEE80211_DEBUG ++ if (crypt && !(fc & IEEE80211_FCTL_WEP) && ++ ieee80211_is_eapol_frame(ieee, skb)) { ++ struct eapol *eap = (struct eapol *)(skb->data + ++ 24); ++ IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", ++ eap_get_type(eap->type)); ++ } ++#endif ++ ++ if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep && ++ !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { ++ IEEE80211_DEBUG_DROP( ++ "dropped unencrypted RX data " ++ "frame from " MAC_FMT ++ " (drop_unencrypted=1)\n", ++ MAC_ARG(hdr->addr2)); ++ goto rx_dropped; ++ } ++/* ++ if(ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { ++ printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n"); ++ } ++*/ ++ /* skb: hdr + (possible reassembled) full plaintext payload */ ++ payload = skb->data + hdrlen; ++ ethertype = (payload[6] << 8) | payload[7]; ++ ++#ifdef NOT_YET ++ /* If IEEE 802.1X is used, check whether the port is authorized to send ++ * the received frame. */ ++ if (ieee->ieee802_1x && ieee->iw_mode == IW_MODE_MASTER) { ++ if (ethertype == ETH_P_PAE) { ++ printk(KERN_DEBUG "%s: RX: IEEE 802.1X frame\n", ++ dev->name); ++ if (ieee->hostapd && ieee->apdev) { ++ /* Send IEEE 802.1X frames to the user ++ * space daemon for processing */ ++ prism2_rx_80211(ieee->apdev, skb, rx_stats, ++ PRISM2_RX_MGMT); ++ ieee->apdevstats.rx_packets++; ++ ieee->apdevstats.rx_bytes += skb->len; ++ goto rx_exit; ++ } ++ } else if (!frame_authorized) { ++ printk(KERN_DEBUG "%s: dropped frame from " ++ "unauthorized port (IEEE 802.1X): " ++ "ethertype=0x%04x\n", ++ dev->name, ethertype); ++ goto rx_dropped; ++ } ++ } ++#endif ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_rx_process_dataframe) ++ { ++ if(ieee->ext_patch_ieee80211_rx_process_dataframe(ieee, skb, rx_stats)) ++ { ++ stats->rx_packets++; ++ stats->rx_bytes += skb->len; ++ goto rx_exit; ++ } ++ else ++ goto rx_dropped; ++ } ++#endif ++ ieee->NumRxDataInPeriod++; ++// ieee->NumRxOkTotal++; ++ /* convert hdr + possible LLC headers into Ethernet header */ ++ if (skb->len - hdrlen >= 8 && ++ ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 && ++ ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || ++ memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) { ++ /* remove RFC1042 or Bridge-Tunnel encapsulation and ++ * replace EtherType */ ++ skb_pull(skb, hdrlen + SNAP_SIZE); ++ memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); ++ memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); ++ } else { ++ u16 len; ++ /* Leave Ethernet header part of hdr and full payload */ ++ skb_pull(skb, hdrlen); ++ len = htons(skb->len); ++ memcpy(skb_push(skb, 2), &len, 2); ++ memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); ++ memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); ++ } ++ ++#ifdef NOT_YET ++ if (wds && ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == ++ IEEE80211_FCTL_TODS) && ++ skb->len >= ETH_HLEN + ETH_ALEN) { ++ /* Non-standard frame: get addr4 from its bogus location after ++ * the payload */ ++ memcpy(skb->data + ETH_ALEN, ++ skb->data + skb->len - ETH_ALEN, ETH_ALEN); ++ skb_trim(skb, skb->len - ETH_ALEN); ++ } ++#endif ++ ++ stats->rx_packets++; ++ stats->rx_bytes += skb->len; ++ ++#ifdef NOT_YET ++ if (ieee->iw_mode == IW_MODE_MASTER && !wds && ++ ieee->ap->bridge_packets) { ++ if (dst[0] & 0x01) { ++ /* copy multicast frame both to the higher layers and ++ * to the wireless media */ ++ ieee->ap->bridged_multicast++; ++ skb2 = skb_clone(skb, GFP_ATOMIC); ++ if (skb2 == NULL) ++ printk(KERN_DEBUG "%s: skb_clone failed for " ++ "multicast frame\n", dev->name); ++ } else if (hostap_is_sta_assoc(ieee->ap, dst)) { ++ /* send frame directly to the associated STA using ++ * wireless media and not passing to higher layers */ ++ ieee->ap->bridged_unicast++; ++ skb2 = skb; ++ skb = NULL; ++ } ++ } ++ ++ if (skb2 != NULL) { ++ /* send to wireless media */ ++ skb2->protocol = __constant_htons(ETH_P_802_3); ++ skb2->mac.raw = skb2->nh.raw = skb2->data; ++ /* skb2->nh.raw = skb2->data + ETH_HLEN; */ ++ skb2->dev = dev; ++ dev_queue_xmit(skb2); ++ } ++ ++#endif ++ if (skb) { ++ //printk("0skb_len(%d)\n", skb->len); ++ skb->protocol = eth_type_trans(skb, dev); ++ memset(skb->cb, 0, sizeof(skb->cb)); ++ skb->dev = dev; ++ skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */ ++ //skb->ip_summed = CHECKSUM_UNNECESSARY; /* 802.11 crc not sufficient */ ++ ieee->last_rx_ps_time = jiffies; ++ //printk("1skb_len(%d)\n", skb->len); ++ netif_rx(skb); ++ } ++ ++//by lizhaoming for LED_RX 2008.6.23 ++#ifdef LED_SHIN ++// printk("==================>data rcvd\n"); ++ ieee->ieee80211_led_contorl(dev,LED_CTL_RX); ++#endif ++ ++ rx_exit: ++#ifdef NOT_YET ++ if (sta) ++ hostap_handle_sta_release(sta); ++#endif ++ return 1; ++ ++ rx_dropped: ++ stats->rx_dropped++; ++#if 0 ++ int i; ++ printk("======>dropped: %s():addr2:"MAC_FMT",addr1:"MAC_FMT",skb->len:%d, hdrlen:%d\n", __FUNCTION__, MAC_ARG(((struct ieee80211_hdr*)skb->data)->addr2), MAC_ARG(((struct ieee80211_hdr*)skb->data)->addr1), skb->len, hdrlen); ++ for (i = 0; i < skb->len; i++) { ++ if (i % 16 == 0) printk("\n\t"); ++ printk("%2x ", *(skb->data+i)); ++ } ++ ++ printk("\n"); ++#endif ++ /* Returning 0 indicates to caller that we have not handled the SKB-- ++ * so it is still allocated and can be used again by underlying ++ * hardware as a DMA target */ ++ return 0; ++} ++ ++#ifdef _RTL8187_EXT_PATCH_ ++int ieee_ext_skb_p80211_to_ether(struct sk_buff *skb, int hdrlen, u8 *dst, u8 *src) ++{ ++ u8 *payload; ++ u16 ethertype; ++ ++ /* skb: hdr + (possible reassembled) full plaintext payload */ ++ payload = skb->data + hdrlen; ++ ethertype = (payload[6] << 8) | payload[7]; ++ ++ /* convert hdr + possible LLC headers into Ethernet header */ ++ if (skb->len - hdrlen >= 8 && ++ ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 && ++ ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || ++ memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) { ++ /* remove RFC1042 or Bridge-Tunnel encapsulation and ++ * replace EtherType */ ++ skb_pull(skb, hdrlen + SNAP_SIZE); ++ memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); ++ memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); ++ } else { ++ u16 len; ++ /* Leave Ethernet header part of hdr and full payload */ ++ skb_pull(skb, hdrlen); ++ len = htons(skb->len); ++ memcpy(skb_push(skb, 2), &len, 2); ++ memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); ++ memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); ++ } ++ ++ return 1; ++} ++#endif // _RTL8187_EXT_PATCH_ ++ ++ ++#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 ++ ++static inline int ieee80211_is_ofdm_rate(u8 rate) ++{ ++ switch (rate & ~IEEE80211_BASIC_RATE_MASK) { ++ case IEEE80211_OFDM_RATE_6MB: ++ case IEEE80211_OFDM_RATE_9MB: ++ case IEEE80211_OFDM_RATE_12MB: ++ case IEEE80211_OFDM_RATE_18MB: ++ case IEEE80211_OFDM_RATE_24MB: ++ case IEEE80211_OFDM_RATE_36MB: ++ case IEEE80211_OFDM_RATE_48MB: ++ case IEEE80211_OFDM_RATE_54MB: ++ return 1; ++ } ++ return 0; ++} ++ ++ ++// ++// Description: ++// Translate 0-100 signal strength index into dBm. ++// ++int ++TranslateToDbm8187( ++ unsigned char SignalStrengthIndex // 0-100 index. ++ ) ++{ ++ unsigned char SignalPower; // in dBm. ++ ++ // Translate to dBm (x=0.5y-95). ++ //SignalPower = (int)((SignalStrengthIndex + 1) >> 1); ++ SignalPower = (int)SignalStrengthIndex * 7 / 10; ++ SignalPower -= 95; ++// printk("==>SignalPower:%d\n", SignalPower); ++ return SignalPower; ++} ++ ++static inline int ieee80211_SignalStrengthTranslate( ++ int CurrSS ++ ) ++{ ++ int RetSS; ++ ++ // Step 1. Scale mapping. ++ if(CurrSS >= 71 && CurrSS <= 100) ++ { ++ RetSS = 95 + (((CurrSS - 70) / 6 == 5) ? 5 : ((CurrSS - 70) / 6 + 1)); ++ } ++ else if(CurrSS >= 41 && CurrSS <= 70) ++ { ++ RetSS = 83 + ((CurrSS - 40) / 3); ++ } ++ else if(CurrSS >= 31 && CurrSS <= 40) ++ { ++ RetSS = 71 + (CurrSS - 30); ++ } ++ else if(CurrSS >= 21 && CurrSS <= 30) ++ { ++ RetSS = 59 + (CurrSS - 20); ++ } ++ else if(CurrSS >= 5 && CurrSS <= 20) ++ { ++ RetSS = 47 + (((CurrSS - 5) * 2) / 3); ++ } ++ else if(CurrSS == 4) ++ { ++ RetSS = 37; ++ } ++ else if(CurrSS == 3) ++ { ++ RetSS = 27; ++ } ++ else if(CurrSS == 2) ++ { ++ RetSS = 18; ++ } ++ else if(CurrSS == 1) ++ { ++ RetSS = 9; ++ } ++ else ++ { ++ RetSS = CurrSS; ++ } ++ //RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS)); ++ ++ // Step 2. Smoothing. ++ ++ //RT_TRACE(COMP_DBG, DBG_LOUD, ("$$$$$ After Smoothing: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS)); ++ ++ return RetSS; ++} ++ ++#ifdef ENABLE_DOT11D ++static inline void ieee80211_extract_country_ie( ++ struct ieee80211_device *ieee, ++ struct ieee80211_info_element *info_element, ++ struct ieee80211_network *network, ++ u8 * addr2 ++) ++{ ++#if 0 ++ u32 i = 0; ++ u8 * p = (u8*)info_element->data; ++ printk("-----------------------\n"); ++ printk("%s Country IE:", network->ssid); ++ for(i=0; ilen; i++) ++ printk("\t%2.2x", *(p+i)); ++ printk("\n-----------------------\n"); ++#endif ++ if(IS_DOT11D_ENABLE(ieee)) ++ { ++ if(info_element->len!= 0) ++ { ++ memcpy(network->CountryIeBuf, info_element->data, info_element->len); ++ network->CountryIeLen = info_element->len; ++ ++ if(!IS_COUNTRY_IE_VALID(ieee)) ++ { ++ Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data); ++ } ++ } ++ ++ // ++ // 070305, rcnjko: I update country IE watch dog here because ++ // some AP (e.g. Cisco 1242) don't include country IE in their ++ // probe response frame. ++ // ++ if(IS_EQUAL_CIE_SRC(ieee, addr2) ) ++ { ++ UPDATE_CIE_WATCHDOG(ieee); ++ } ++ } ++ ++} ++#endif ++ ++ ++ inline int ieee80211_network_init( ++ struct ieee80211_device *ieee, ++ struct ieee80211_probe_response *beacon, ++ struct ieee80211_network *network, ++ struct ieee80211_rx_stats *stats) ++{ ++#ifdef CONFIG_IEEE80211_DEBUG ++ char rates_str[64]; ++ char *p; ++#endif ++ struct ieee80211_info_element *info_element; ++ u16 left; ++ u8 i; ++ short offset; ++ ++ /* Pull out fixed field data */ ++ memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); ++ network->capability = beacon->capability; ++ network->last_scanned = jiffies; ++ network->time_stamp[0] = beacon->time_stamp[0]; ++ network->time_stamp[1] = beacon->time_stamp[1]; ++ network->beacon_interval = beacon->beacon_interval; ++ /* Where to pull this? beacon->listen_interval;*/ ++ network->listen_interval = 0x0A; ++ network->rates_len = network->rates_ex_len = 0; ++ network->last_associate = 0; ++ network->ssid_len = 0; ++ network->flags = 0; ++ network->atim_window = 0; ++ network->QoS_Enable = 0; ++#ifdef THOMAS_TURBO ++ network->Turbo_Enable = 0; ++#endif ++#ifdef ENABLE_DOT11D ++ network->CountryIeLen = 0; ++ memset(network->CountryIeBuf, 0, MAX_IE_LEN); ++#endif ++ ++ if (stats->freq == IEEE80211_52GHZ_BAND) { ++ /* for A band (No DS info) */ ++ network->channel = stats->received_channel; ++ } else ++ network->flags |= NETWORK_HAS_CCK; ++ ++ network->wpa_ie_len = 0; ++ network->rsn_ie_len = 0; ++ ++ info_element = &beacon->info_element; ++ left = stats->len - ((void *)info_element - (void *)beacon); ++ while (left >= sizeof(struct ieee80211_info_element_hdr)) { ++ if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) { ++ IEEE80211_DEBUG_SCAN("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%d left=%d.\n", ++ info_element->len + sizeof(struct ieee80211_info_element), ++ left); ++ return 1; ++ } ++ ++ switch (info_element->id) { ++ case MFIE_TYPE_SSID: ++ if (ieee80211_is_empty_essid(info_element->data, ++ info_element->len)) { ++ network->flags |= NETWORK_EMPTY_ESSID; ++ break; ++ } ++ ++ network->ssid_len = min(info_element->len, ++ (u8)IW_ESSID_MAX_SIZE); ++ memcpy(network->ssid, info_element->data, network->ssid_len); ++ if (network->ssid_len < IW_ESSID_MAX_SIZE) ++ memset(network->ssid + network->ssid_len, 0, ++ IW_ESSID_MAX_SIZE - network->ssid_len); ++ ++ IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n", ++ network->ssid, network->ssid_len); ++ break; ++ ++ case MFIE_TYPE_RATES: ++#ifdef CONFIG_IEEE80211_DEBUG ++ p = rates_str; ++#endif ++ network->rates_len = min(info_element->len, MAX_RATES_LENGTH); ++ for (i = 0; i < network->rates_len; i++) { ++ network->rates[i] = info_element->data[i]; ++#ifdef CONFIG_IEEE80211_DEBUG ++ p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]); ++#endif ++ if (ieee80211_is_ofdm_rate(info_element->data[i])) { ++ network->flags |= NETWORK_HAS_OFDM; ++ if (info_element->data[i] & ++ IEEE80211_BASIC_RATE_MASK) ++ network->flags &= ++ ~NETWORK_HAS_CCK; ++ } ++ } ++ ++ IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n", ++ rates_str, network->rates_len); ++ break; ++ ++ case MFIE_TYPE_RATES_EX: ++#ifdef CONFIG_IEEE80211_DEBUG ++ p = rates_str; ++#endif ++ network->rates_ex_len = min(info_element->len, MAX_RATES_EX_LENGTH); ++ for (i = 0; i < network->rates_ex_len; i++) { ++ network->rates_ex[i] = info_element->data[i]; ++#ifdef CONFIG_IEEE80211_DEBUG ++ p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]); ++#endif ++ if (ieee80211_is_ofdm_rate(info_element->data[i])) { ++ network->flags |= NETWORK_HAS_OFDM; ++ if (info_element->data[i] & ++ IEEE80211_BASIC_RATE_MASK) ++ network->flags &= ++ ~NETWORK_HAS_CCK; ++ } ++ } ++ ++ IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n", ++ rates_str, network->rates_ex_len); ++ break; ++ ++ case MFIE_TYPE_DS_SET: ++ IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n", ++ info_element->data[0]); ++ if (stats->freq == IEEE80211_24GHZ_BAND) ++ network->channel = info_element->data[0]; ++ break; ++ ++ case MFIE_TYPE_FH_SET: ++ IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n"); ++ break; ++ ++ case MFIE_TYPE_CF_SET: ++ IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n"); ++ break; ++ ++ case MFIE_TYPE_TIM: ++ ++ if(info_element->len < 4) ++ break; ++ ++ network->dtim_period = info_element->data[1]; ++ ++ if(ieee->state != IEEE80211_LINKED) ++ break; ++ ++ network->last_dtim_sta_time[0] = stats->mac_time[0]; ++ network->last_dtim_sta_time[1] = stats->mac_time[1]; ++ ++ network->dtim_data = IEEE80211_DTIM_VALID; ++ ++ if(info_element->data[0] != 0) ++ break; ++ ++ if(info_element->data[2] & 1) ++ network->dtim_data |= IEEE80211_DTIM_MBCAST; ++ ++ offset = (info_element->data[2] >> 1)*2; ++ ++ //printk("offset1:%x aid:%x\n",offset, ieee->assoc_id); ++ ++ if(ieee->assoc_id < offset || ++ ieee->assoc_id > 8*(offset + info_element->len -3)) ++ ++ break; ++ ++ ++ offset = offset + ieee->assoc_id / 8;// + ((aid % 8)? 0 : 1) ; ++ ++ // printk("offset:%x data:%x, ucast:%d\n", offset, ++ // info_element->data[3+offset] , ++ // info_element->data[3+offset] & (1<<(ieee->assoc_id%8))); ++ ++ if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8))) ++ network->dtim_data |= IEEE80211_DTIM_UCAST; ++ ++ break; ++ ++ case MFIE_TYPE_IBSS_SET: ++ IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n"); ++ break; ++ ++ case MFIE_TYPE_CHALLENGE: ++ IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n"); ++ break; ++ ++ case MFIE_TYPE_GENERIC: ++ //nic is 87B ++ IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n", ++ info_element->len); ++ if (info_element->len >= 4 && ++ info_element->data[0] == 0x00 && ++ info_element->data[1] == 0x50 && ++ info_element->data[2] == 0xf2 && ++ info_element->data[3] == 0x01) { ++ network->wpa_ie_len = min(info_element->len + 2, ++ MAX_WPA_IE_LEN); ++ memcpy(network->wpa_ie, info_element, ++ network->wpa_ie_len); ++ } ++ ++#ifdef THOMAS_TURBO ++ if (info_element->len == 7 && ++ info_element->data[0] == 0x00 && ++ info_element->data[1] == 0xe0 && ++ info_element->data[2] == 0x4c && ++ info_element->data[3] == 0x01 && ++ info_element->data[4] == 0x02) { ++ network->Turbo_Enable = 1; ++ } ++#endif ++ if (1 == stats->nic_type) {//nic 87 ++ break; ++ } ++ ++ if (info_element->len >= 5 && ++ info_element->data[0] == 0x00 && ++ info_element->data[1] == 0x50 && ++ info_element->data[2] == 0xf2 && ++ info_element->data[3] == 0x02 && ++ info_element->data[4] == 0x00) { ++ //printk(KERN_WARNING "wmm info updated: %x\n", info_element->data[6]); ++ //WMM Information Element ++ network->wmm_info = info_element->data[6]; ++ network->QoS_Enable = 1; ++ } ++ ++ if (info_element->len >= 8 && ++ info_element->data[0] == 0x00 && ++ info_element->data[1] == 0x50 && ++ info_element->data[2] == 0xf2 && ++ info_element->data[3] == 0x02 && ++ info_element->data[4] == 0x01) { ++ // Not care about version at present. ++ //WMM Information Element ++ //printk(KERN_WARNING "wmm info¶m updated: %x\n", info_element->data[6]); ++ network->wmm_info = info_element->data[6]; ++ //WMM Parameter Element ++ memcpy(network->wmm_param, (u8 *)(info_element->data + 8),(info_element->len - 8)); ++ network->QoS_Enable = 1; ++ } ++ break; ++ ++ case MFIE_TYPE_RSN: ++ IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n", ++ info_element->len); ++ network->rsn_ie_len = min(info_element->len + 2, ++ MAX_WPA_IE_LEN); ++ memcpy(network->rsn_ie, info_element, ++ network->rsn_ie_len); ++ break; ++ ++#ifdef ENABLE_DOT11D ++ case MFIE_TYPE_COUNTRY: ++ IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n", ++ info_element->len); ++// printk("=====>Receive <%s> Country IE\n",network->ssid); ++ ieee80211_extract_country_ie(ieee, info_element, network, beacon->header.addr2); ++ break; ++#endif ++ ++ default: ++ IEEE80211_DEBUG_SCAN("unsupported IE %d\n", ++ info_element->id); ++ break; ++ } ++ ++ left -= sizeof(struct ieee80211_info_element_hdr) + ++ info_element->len; ++ info_element = (struct ieee80211_info_element *) ++ &info_element->data[info_element->len]; ++ } ++ ++ network->mode = 0; ++ if (stats->freq == IEEE80211_52GHZ_BAND) ++ network->mode = IEEE_A; ++ else { ++ if (network->flags & NETWORK_HAS_OFDM) ++ network->mode |= IEEE_G; ++ if (network->flags & NETWORK_HAS_CCK) ++ network->mode |= IEEE_B; ++ } ++ ++ if (network->mode == 0) { ++ IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' " ++ "network.\n", ++ escape_essid(network->ssid, ++ network->ssid_len), ++ MAC_ARG(network->bssid)); ++ return 1; ++ } ++ ++ if (ieee80211_is_empty_essid(network->ssid, network->ssid_len)) ++ network->flags |= NETWORK_EMPTY_ESSID; ++ ++#if 1 ++ //if(strcmp(network->ssid, "linksys_lzm000") == 0) ++ // printk("----signalstrength = %d ", stats->signalstrength); ++ stats->signal = TranslateToDbm8187(stats->signalstrength); ++ //stats->noise = stats->signal - stats->noise; ++ stats->noise = TranslateToDbm8187(100 - stats->signalstrength) - 25; ++#endif ++ memcpy(&network->stats, stats, sizeof(network->stats)); ++ ++ //YJ,test,080611 ++ //if(strcmp(network->ssid, "ZyXEL") == 0) ++ // IEEE_NET_DUMP(network); ++ ++ return 0; ++} ++ ++static inline int is_same_network(struct ieee80211_network *src, ++ struct ieee80211_network *dst, ++ struct ieee80211_device * ieee) ++{ ++ /* A network is only a duplicate if the channel, BSSID, ESSID ++ * and the capability field (in particular IBSS and BSS) all match. ++ * We treat all with the same BSSID and channel ++ * as one network */ ++ return (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod,080819,for hidden ap ++ //((src->ssid_len == dst->ssid_len) && ++ (src->channel == dst->channel) && ++ !memcmp(src->bssid, dst->bssid, ETH_ALEN) && ++ (!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod,080819,for hidden ap ++ //!memcmp(src->ssid, dst->ssid, src->ssid_len) && ++ ((src->capability & WLAN_CAPABILITY_IBSS) == ++ (dst->capability & WLAN_CAPABILITY_IBSS)) && ++ ((src->capability & WLAN_CAPABILITY_BSS) == ++ (dst->capability & WLAN_CAPABILITY_BSS))); ++} ++ ++inline void update_network(struct ieee80211_network *dst, ++ struct ieee80211_network *src) ++{ ++ unsigned char quality = src->stats.signalstrength; ++ unsigned char signal = 0; ++ unsigned char noise = 0; ++ if(dst->stats.signalstrength > 0) { ++ quality = (dst->stats.signalstrength * 5 + src->stats.signalstrength + 5)/6; ++ } ++ signal = TranslateToDbm8187(quality); ++ //noise = signal - src->stats.noise; ++ if(dst->stats.noise > 0) ++ noise = (dst->stats.noise * 5 + src->stats.noise)/6; ++ //if(strcmp(dst->ssid, "linksys_lzm000") == 0) ++// printk("ssid:%s, quality:%d, signal:%d\n", dst->ssid, quality, signal); ++ memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); ++ dst->stats.signalstrength = quality; ++ dst->stats.signal = signal; ++ dst->stats.noise = noise; ++ dst->capability = src->capability; ++ memcpy(dst->rates, src->rates, src->rates_len); ++ dst->rates_len = src->rates_len; ++ memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len); ++ dst->rates_ex_len = src->rates_ex_len; ++ ++ //YJ,add,080819,for hidden ap ++ if(src->ssid_len > 0) ++ { ++ //if(src->ssid_len == 13) ++ // printk("=====================>>>>>>>> Dst ssid: %s Src ssid: %s\n", dst->ssid, src->ssid); ++ memset(dst->ssid, 0, dst->ssid_len); ++ dst->ssid_len = src->ssid_len; ++ memcpy(dst->ssid, src->ssid, src->ssid_len); ++ } ++ //YJ,add,080819,for hidden ap,end ++ dst->channel = src->channel; ++ dst->mode = src->mode; ++ dst->flags = src->flags; ++ dst->time_stamp[0] = src->time_stamp[0]; ++ dst->time_stamp[1] = src->time_stamp[1]; ++ ++ dst->beacon_interval = src->beacon_interval; ++ dst->listen_interval = src->listen_interval; ++ dst->atim_window = src->atim_window; ++ dst->dtim_period = src->dtim_period; ++ dst->dtim_data = src->dtim_data; ++ dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0]; ++ dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1]; ++ ++ memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); ++ dst->wpa_ie_len = src->wpa_ie_len; ++ memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len); ++ dst->rsn_ie_len = src->rsn_ie_len; ++ ++ dst->last_scanned = jiffies; ++ /* dst->last_associate is not overwritten */ ++#if 1 ++ dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame. ++/* ++ if((dst->wmm_info^src->wmm_info)&0x0f) {//Param Set Count change, update Parameter ++ memcpy(dst->wmm_param, src->wmm_param, IEEE80211_AC_PRAM_LEN); ++ } ++*/ ++ if(src->wmm_param[0].ac_aci_acm_aifsn|| \ ++ src->wmm_param[1].ac_aci_acm_aifsn|| \ ++ src->wmm_param[2].ac_aci_acm_aifsn|| \ ++ src->wmm_param[1].ac_aci_acm_aifsn) { ++ memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN); ++ } ++ dst->QoS_Enable = src->QoS_Enable; ++#else ++ dst->QoS_Enable = 1;//for Rtl8187 simulation ++#endif ++ dst->SignalStrength = src->SignalStrength; ++#ifdef THOMAS_TURBO ++ dst->Turbo_Enable = src->Turbo_Enable; ++#endif ++#ifdef ENABLE_DOT11D ++ dst->CountryIeLen = src->CountryIeLen; ++ memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen); ++#endif ++ ++} ++ ++inline void ieee80211_process_probe_response( ++ struct ieee80211_device *ieee, ++ struct ieee80211_probe_response *beacon, ++ struct ieee80211_rx_stats *stats) ++{ ++ struct ieee80211_network network; ++ struct ieee80211_network *target; ++ struct ieee80211_network *oldest = NULL; ++#ifdef CONFIG_IEEE80211_DEBUG ++ struct ieee80211_info_element *info_element = &beacon->info_element; ++#endif ++ unsigned long flags; ++ short renew; ++ u8 wmm_info; ++ u8 is_beacon = (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_BEACON)? 1:0; ++ ++ memset(&network, 0, sizeof(struct ieee80211_network)); ++//rz ++#ifdef _RTL8187_EXT_PATCH_ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_process_probe_response_1) { ++ ieee->ext_patch_ieee80211_process_probe_response_1(ieee, beacon, stats); ++ return; ++ } ++#endif ++ IEEE80211_DEBUG_SCAN( ++ "'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", ++ escape_essid(info_element->data, info_element->len), ++ MAC_ARG(beacon->header.addr3), ++ (beacon->capability & (1<<0xf)) ? '1' : '0', ++ (beacon->capability & (1<<0xe)) ? '1' : '0', ++ (beacon->capability & (1<<0xd)) ? '1' : '0', ++ (beacon->capability & (1<<0xc)) ? '1' : '0', ++ (beacon->capability & (1<<0xb)) ? '1' : '0', ++ (beacon->capability & (1<<0xa)) ? '1' : '0', ++ (beacon->capability & (1<<0x9)) ? '1' : '0', ++ (beacon->capability & (1<<0x8)) ? '1' : '0', ++ (beacon->capability & (1<<0x7)) ? '1' : '0', ++ (beacon->capability & (1<<0x6)) ? '1' : '0', ++ (beacon->capability & (1<<0x5)) ? '1' : '0', ++ (beacon->capability & (1<<0x4)) ? '1' : '0', ++ (beacon->capability & (1<<0x3)) ? '1' : '0', ++ (beacon->capability & (1<<0x2)) ? '1' : '0', ++ (beacon->capability & (1<<0x1)) ? '1' : '0', ++ (beacon->capability & (1<<0x0)) ? '1' : '0'); ++ ++ if (ieee80211_network_init(ieee, beacon, &network, stats)) { ++ IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n", ++ escape_essid(info_element->data, ++ info_element->len), ++ MAC_ARG(beacon->header.addr3), ++ WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == ++ IEEE80211_STYPE_PROBE_RESP ? ++ "PROBE RESPONSE" : "BEACON"); ++ return; ++ } ++ ++#ifdef ENABLE_DOT11D ++ // For Asus EeePc request, ++ // (1) if wireless adapter receive get any 802.11d country code in AP beacon, ++ // wireless adapter should follow the country code. ++ // (2) If there is no any country code in beacon, ++ // then wireless adapter should do active scan from ch1~11 and ++ // passive scan from ch12~14 ++ if(ieee->bGlobalDomain) ++ { ++ if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP) ++ { ++ // Case 1: Country code ++ if(IS_COUNTRY_IE_VALID(ieee) ) ++ { ++ if( !IsLegalChannel(ieee, network.channel) ) ++ { ++ printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel); ++ return; ++ } ++ } ++ // Case 2: No any country code. ++ else ++ { ++ // Filter over channel ch12~14 ++ if(network.channel > 11) ++ { ++ printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel); ++ return; ++ } ++ } ++ } ++ else ++ { ++ // Case 1: Country code ++ if(IS_COUNTRY_IE_VALID(ieee) ) ++ { ++ if( !IsLegalChannel(ieee, network.channel) ) ++ { ++ printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network.channel); ++ return; ++ } ++ } ++ // Case 2: No any country code. ++ else ++ { ++ // Filter over channel ch12~14 ++ if(network.channel > 14) ++ { ++ printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network.channel); ++ return; ++ } ++ } ++ } ++ } ++ ++ //lzm add 081205 ++ // for Toshiba request, we use channel_plan COUNTRY_CODE_WORLD_WIDE_13_INDEX, ++ // For Liteon "World Wide 13" Domain name:ch1~11 active scan & ch12~13 passive scan ++ // So we shoud only rcv beacon in 12-13, and filter probe resp in 12-13. ++ if(ieee->MinPassiveChnlNum != MAX_CHANNEL_NUMBER+1) ++ { ++ if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP) ++ { ++ // Filter over channel ch12~13 ++ if(network.channel >= ieee->MinPassiveChnlNum) ++ { ++ printk("GetScanInfo(): passive scan, filter probe resp at channel(%d).\n", network.channel); ++ return; ++ } ++ } ++ } ++#endif ++ ++ ++ /* The network parsed correctly -- so now we scan our known networks ++ * to see if we can find it in our list. ++ * ++ * NOTE: This search is definitely not optimized. Once its doing ++ * the "right thing" we'll optimize it for efficiency if ++ * necessary */ ++ ++ /* Search for this entry in the list and update it if it is ++ * already there. */ ++ ++ spin_lock_irqsave(&ieee->lock, flags); ++ ++ if(is_same_network(&ieee->current_network, &network, ieee)) { ++ //YJ,add,080819,for hidden ap ++ if(is_beacon == 0) ++ network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags); ++ if ((ieee->state == IEEE80211_LINKED) && is_beacon) ++ ieee->NumRxBcnInPeriod++; ++ wmm_info = ieee->current_network.wmm_info; ++ update_network(&ieee->current_network, &network); ++ } ++ ++ list_for_each_entry(target, &ieee->network_list, list) { ++ if (is_same_network(target, &network, ieee)) ++ break; ++ if ((oldest == NULL) || ++ (target->last_scanned < oldest->last_scanned)) ++ oldest = target; ++ } ++ ++ /* If we didn't find a match, then get a new network slot to initialize ++ * with this beacon's information */ ++ if (&target->list == &ieee->network_list) { ++ if (list_empty(&ieee->network_free_list)) { ++ /* If there are no more slots, expire the oldest */ ++ list_del(&oldest->list); ++ target = oldest; ++ IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from " ++ "network list.\n", ++ escape_essid(target->ssid, ++ target->ssid_len), ++ MAC_ARG(target->bssid)); ++ } else { ++ /* Otherwise just pull from the free list */ ++ target = list_entry(ieee->network_free_list.next, ++ struct ieee80211_network, list); ++ list_del(ieee->network_free_list.next); ++ } ++ ++ ++#ifdef CONFIG_IEEE80211_DEBUG ++ IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n", ++ escape_essid(network.ssid, ++ network.ssid_len), ++ MAC_ARG(network.bssid), ++ WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == ++ IEEE80211_STYPE_PROBE_RESP ? ++ "PROBE RESPONSE" : "BEACON"); ++#endif ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ network.ext_entry = target->ext_entry; ++#endif ++ memcpy(target, &network, sizeof(*target)); ++ list_add_tail(&target->list, &ieee->network_list); ++ if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) ++ ieee80211_softmac_new_net(ieee,&network); ++ } else { ++ IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n", ++ escape_essid(target->ssid, ++ target->ssid_len), ++ MAC_ARG(target->bssid), ++ WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == ++ IEEE80211_STYPE_PROBE_RESP ? ++ "PROBE RESPONSE" : "BEACON"); ++ ++ /* we have an entry and we are going to update it. But this entry may ++ * be already expired. In this case we do the same as we found a new ++ * net and call the new_net handler ++ */ ++ renew = !time_after(target->last_scanned + ieee->scan_age, jiffies); ++ //YJ,add,080819,for hidden ap ++ if(is_beacon == 0) ++ network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags); ++ //if(strncmp(network.ssid, "linksys-c",9) == 0) ++ // printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags); ++ if(((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \ ++ && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\ ++ ||((ieee->current_network.ssid_len == network.ssid_len)&&(strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0)&&(ieee->state == IEEE80211_NOLINK)))) ++ renew = 1; ++ //YJ,add,080819,for hidden ap,end ++ update_network(target, &network); ++ if(renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)) ++ ieee80211_softmac_new_net(ieee,&network); ++ } ++ ++ spin_unlock_irqrestore(&ieee->lock, flags); ++} ++ ++void ieee80211_rx_mgt(struct ieee80211_device *ieee, ++ struct ieee80211_hdr *header, ++ struct ieee80211_rx_stats *stats) ++{ ++ switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { ++ ++ case IEEE80211_STYPE_BEACON: ++ IEEE80211_DEBUG_MGMT("received BEACON (%d)\n", ++ WLAN_FC_GET_STYPE(header->frame_ctl)); ++ IEEE80211_DEBUG_SCAN("Beacon\n"); ++ ieee80211_process_probe_response( ++ ieee, (struct ieee80211_probe_response *)header, stats); ++ break; ++ ++ case IEEE80211_STYPE_PROBE_RESP: ++ IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n", ++ WLAN_FC_GET_STYPE(header->frame_ctl)); ++ IEEE80211_DEBUG_SCAN("Probe response\n"); ++ ieee80211_process_probe_response( ++ ieee, (struct ieee80211_probe_response *)header, stats); ++ break; ++//rz ++#ifdef _RTL8187_EXT_PATCH_ ++ case IEEE80211_STYPE_PROBE_REQ: ++ IEEE80211_DEBUG_MGMT("received PROBE REQUEST (%d)\n", ++ WLAN_FC_GET_STYPE(header->frame_ctl)); ++ IEEE80211_DEBUG_SCAN("Probe request\n"); ++ /// ++ //printk("Probe request\n"); ++ if( ieee->iw_mode == ieee->iw_ext_mode && ieee->ext_patch_ieee80211_rx_mgt_on_probe_req ) ++ ieee->ext_patch_ieee80211_rx_mgt_on_probe_req( ieee, (struct ieee80211_probe_request *)header, stats); ++ break; ++#endif // _RTL8187_EXT_PATCH_ ++ ++ } ++} ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++EXPORT_SYMBOL(ieee80211_rx_mgt); ++EXPORT_SYMBOL(ieee80211_rx); ++EXPORT_SYMBOL(ieee80211_network_init); ++#ifdef _RTL8187_EXT_PATCH_ ++EXPORT_SYMBOL(ieee_ext_skb_p80211_to_ether); ++#endif ++#else ++EXPORT_SYMBOL_NOVERS(ieee80211_rx_mgt); ++EXPORT_SYMBOL_NOVERS(ieee80211_rx); ++EXPORT_SYMBOL_NOVERS(ieee80211_network_init); ++#ifdef _RTL8187_EXT_PATCH_ ++EXPORT_SYMBOL_NOVERS(ieee_ext_skb_p80211_to_ether); ++#endif ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_softmac.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_softmac.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_softmac.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_softmac.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,4083 @@ ++/* IEEE 802.11 SoftMAC layer ++ * Copyright (c) 2005 Andrea Merello ++ * ++ * Mostly extracted from the rtl8180-sa2400 driver for the ++ * in-kernel generic ieee802.11 stack. ++ * ++ * Few lines might be stolen from other part of the ieee80211 ++ * stack. Copyright who own it's copyright ++ * ++ * WPA code stolen from the ipw2200 driver. ++ * Copyright who own it's copyright. ++ * ++ * released under the GPL ++ */ ++ ++ ++#include "ieee80211.h" ++ ++#include ++#include ++#include ++#include ++ ++#ifdef ENABLE_DOT11D ++#include "dot11d.h" ++#endif ++ ++ ++u8 rsn_authen_cipher_suite[16][4] = { ++ {0x00,0x0F,0xAC,0x00}, //Use group key, //Reserved ++ {0x00,0x0F,0xAC,0x01}, //WEP-40 //RSNA default ++ {0x00,0x0F,0xAC,0x02}, //TKIP //NONE //{used just as default} ++ {0x00,0x0F,0xAC,0x03}, //WRAP-historical ++ {0x00,0x0F,0xAC,0x04}, //CCMP ++ {0x00,0x0F,0xAC,0x05}, //WEP-104 ++}; ++ ++short ieee80211_is_54g(struct ieee80211_network net) ++{ ++ return ((net.rates_ex_len > 0) || (net.rates_len > 4)); ++} ++ ++short ieee80211_is_shortslot(struct ieee80211_network net) ++{ ++ return (net.capability & WLAN_CAPABILITY_SHORT_SLOT); ++} ++ ++/* returns the total length needed for pleacing the RATE MFIE ++ * tag and the EXTENDED RATE MFIE tag if needed. ++ * It encludes two bytes per tag for the tag itself and its len ++ */ ++unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee) ++{ ++ unsigned int rate_len = 0; ++ ++ if (ieee->modulation & IEEE80211_CCK_MODULATION) ++ rate_len = IEEE80211_CCK_RATE_LEN + 2; ++ ++ if (ieee->modulation & IEEE80211_OFDM_MODULATION) ++ ++ rate_len += IEEE80211_OFDM_RATE_LEN + 2; ++ ++ return rate_len; ++} ++ ++/* pleace the MFIE rate, tag to the memory (double) poined. ++ * Then it updates the pointer so that ++ * it points after the new MFIE tag added. ++ */ ++void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p) ++{ ++ u8 *tag = *tag_p; ++ ++ if (ieee->modulation & IEEE80211_CCK_MODULATION){ ++ *tag++ = MFIE_TYPE_RATES; ++ *tag++ = 7; ++ *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; ++ *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; ++ *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; ++ *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; ++ //added for basic rate set ++ *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; ++ *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; ++ *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; ++ } ++ ++ /* We may add an option for custom rates that specific HW might support */ ++ *tag_p = tag; ++} ++ ++void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p) ++{ ++ u8 *tag = *tag_p; ++ ++ if (ieee->modulation & IEEE80211_OFDM_MODULATION){ ++ ++ *tag++ = MFIE_TYPE_RATES_EX; ++ *tag++ = 5; ++ *tag++ = IEEE80211_OFDM_RATE_9MB; ++ *tag++ = IEEE80211_OFDM_RATE_18MB; ++ *tag++ = IEEE80211_OFDM_RATE_36MB; ++ *tag++ = IEEE80211_OFDM_RATE_48MB; ++ *tag++ = IEEE80211_OFDM_RATE_54MB; ++ ++ } ++ ++ /* We may add an option for custom rates that specific HW might support */ ++ *tag_p = tag; ++} ++ ++ ++void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) { ++ u8 *tag = *tag_p; ++ ++ *tag++ = MFIE_TYPE_GENERIC; //0 ++ *tag++ = 7; ++ *tag++ = 0x00; ++ *tag++ = 0x50; ++ *tag++ = 0xf2; ++ *tag++ = 0x02;//5 ++ *tag++ = 0x00; ++ *tag++ = 0x01; ++#ifdef SUPPORT_USPD ++ if(ieee->current_network.wmm_info & 0x80) { ++ *tag++ = 0x0f|MAX_SP_Len; ++ } else { ++ *tag++ = MAX_SP_Len; ++ } ++#else ++ *tag++ = MAX_SP_Len; ++#endif ++ *tag_p = tag; ++} ++ ++#ifdef THOMAS_TURBO ++void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) { ++ u8 *tag = *tag_p; ++ ++ *tag++ = MFIE_TYPE_GENERIC; //0 ++ *tag++ = 7; ++ *tag++ = 0x00; ++ *tag++ = 0xe0; ++ *tag++ = 0x4c; ++ *tag++ = 0x01;//5 ++ *tag++ = 0x02; ++ *tag++ = 0x11; ++ *tag++ = 0x00; ++ ++ *tag_p = tag; ++ printk(KERN_ALERT "This is enable turbo mode IE process\n"); ++} ++#endif ++ ++void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb) ++{ ++ int nh; ++ nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM; ++ ++/* ++ * if the queue is full but we have newer frames then ++ * just overwrites the oldest. ++ * ++ * if (nh == ieee->mgmt_queue_tail) ++ * return -1; ++ */ ++ ieee->mgmt_queue_head = nh; ++ ieee->mgmt_queue_ring[nh] = skb; ++ ++ //return 0; ++} ++ ++struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee) ++{ ++ struct sk_buff *ret; ++ ++ if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head) ++ return NULL; ++ ++ ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail]; ++ ++ ieee->mgmt_queue_tail = ++ (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM; ++ ++ return ret; ++} ++ ++void init_mgmt_queue(struct ieee80211_device *ieee) ++{ ++ ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0; ++} ++ ++ ++void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl); ++ ++inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee) ++{ ++ unsigned long flags; ++ short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; ++ struct ieee80211_hdr_3addr *header= ++ (struct ieee80211_hdr_3addr *) skb->data; ++ ++ ++ spin_lock_irqsave(&ieee->lock, flags); ++ ++ /* called with 2nd param 0, no mgmt lock required */ ++ ieee80211_sta_wakeup(ieee,0); ++ ++ if(single){ ++ if(ieee->queue_stop){ ++ ++ enqueue_mgmt(ieee,skb); ++ }else{ ++ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4); ++ ++ if (ieee->seq_ctrl[0] == 0xFFF) ++ ieee->seq_ctrl[0] = 0; ++ else ++ ieee->seq_ctrl[0]++; ++ ++ /* avoid watchdog triggers */ ++ ieee->dev->trans_start = jiffies; ++ ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) ++// dev_kfree_skb_any(skb);//edit by thomas //'cause this function will cause Oops called in interrupt context in old version 101907 ++#endif ++ } ++ ++ spin_unlock_irqrestore(&ieee->lock, flags); ++ }else{ ++ spin_unlock_irqrestore(&ieee->lock, flags); ++ spin_lock_irqsave(&ieee->mgmt_tx_lock, flags); ++ ++ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); ++ ++ if (ieee->seq_ctrl[0] == 0xFFF) ++ ieee->seq_ctrl[0] = 0; ++ else ++ ieee->seq_ctrl[0]++; ++ ++ ieee->softmac_hard_start_xmit(skb,ieee->dev); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) ++// dev_kfree_skb_any(skb);//edit by thomas ++#endif ++ spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags); ++ } ++} ++ ++ ++inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee) ++{ ++ ++ short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; ++ struct ieee80211_hdr_3addr *header = ++ (struct ieee80211_hdr_3addr *) skb->data; ++ ++ ++ if(single){ ++ ++ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); ++ ++ if (ieee->seq_ctrl[0] == 0xFFF) ++ ieee->seq_ctrl[0] = 0; ++ else ++ ieee->seq_ctrl[0]++; ++ ++ /* avoid watchdog triggers */ ++ ieee->dev->trans_start = jiffies; ++ ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); ++ ++ }else{ ++ ++ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); ++ ++ if (ieee->seq_ctrl[0] == 0xFFF) ++ ieee->seq_ctrl[0] = 0; ++ else ++ ieee->seq_ctrl[0]++; ++ ++ ieee->softmac_hard_start_xmit(skb,ieee->dev); ++ ++ } ++ dev_kfree_skb_any(skb);//edit by thomas ++} ++ ++inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee) ++{ ++ unsigned int len,rate_len; ++ u8 *tag; ++ struct sk_buff *skb; ++ struct ieee80211_probe_request *req; ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ short extMore = 0; ++ if(ieee->ext_patch_ieee80211_probe_req_1) ++ extMore = ieee->ext_patch_ieee80211_probe_req_1(ieee); ++#endif ++ ++ len = ieee->current_network.ssid_len; ++ ++ rate_len = ieee80211_MFIE_rate_len(ieee); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(!extMore) ++#endif ++ skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) + ++ 2 + len + rate_len); ++#ifdef _RTL8187_EXT_PATCH_ ++ else ++ skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) + ++ 2 + len + rate_len+128); // MESHID + CAP ++#endif ++ ++ if (!skb) ++ return NULL; ++ ++ req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request)); ++ req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); ++ req->header.duration_id = 0; //FIXME: is this OK ? ++ ++ memset(req->header.addr1, 0xff, ETH_ALEN); ++ memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN); ++ memset(req->header.addr3, 0xff, ETH_ALEN); ++ ++ tag = (u8 *) skb_put(skb,len+2+rate_len); ++ ++ *tag++ = MFIE_TYPE_SSID; ++ *tag++ = len; ++ memcpy(tag, ieee->current_network.ssid, len); ++ tag += len; ++ ++ ieee80211_MFIE_Brate(ieee,&tag); ++ ieee80211_MFIE_Grate(ieee,&tag); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(extMore) ++ ieee->ext_patch_ieee80211_probe_req_2(ieee, skb, tag); ++#endif ++ return skb; ++} ++ ++struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++void ext_ieee80211_send_beacon_wq(struct work_struct *work) ++{ ++ struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, ext_send_beacon_wq); ++#else ++void ext_ieee80211_send_beacon_wq(struct ieee80211_device *ieee) ++{ ++#endif ++ ++ struct sk_buff *skb; ++ ++ //unsigned long flags; ++// printk("=========>%s()\n", __FUNCTION__); ++ skb = ieee80211_get_beacon_(ieee); ++ ++ if (skb){ ++ softmac_mgmt_xmit(skb, ieee); ++ ieee->softmac_stats.tx_beacons++; ++ dev_kfree_skb_any(skb);//edit by thomas ++ } ++ ++ ++ //printk(KERN_WARNING "[1] beacon sending!\n"); ++// ieee->beacon_timer.expires = jiffies + ++// (MSECS( ieee->current_network.beacon_interval -5)); ++ ++ //spin_lock_irqsave(&ieee->beacon_lock,flags); ++// if(ieee->beacon_txing) ++// add_timer(&ieee->beacon_timer); ++ //spin_unlock_irqrestore(&ieee->beacon_lock,flags); ++} ++#endif ++ ++void ieee80211_send_beacon(struct ieee80211_device *ieee) ++{ ++ struct sk_buff *skb; ++ ++ //unsigned long flags; ++// printk("=========>%s()\n", __FUNCTION__); ++ skb = ieee80211_get_beacon_(ieee); ++ ++ if (skb){ ++ softmac_mgmt_xmit(skb, ieee); ++ ieee->softmac_stats.tx_beacons++; ++ dev_kfree_skb_any(skb);//edit by thomas ++ } ++ ++ ++ //printk(KERN_WARNING "[1] beacon sending!\n"); ++ ieee->beacon_timer.expires = jiffies + ++ (MSECS( ieee->current_network.beacon_interval -5)); ++ ++ //spin_lock_irqsave(&ieee->beacon_lock,flags); ++ if(ieee->beacon_txing) ++ add_timer(&ieee->beacon_timer); ++ //spin_unlock_irqrestore(&ieee->beacon_lock,flags); ++} ++ ++ ++void ieee80211_send_beacon_cb(unsigned long _ieee) ++{ ++ struct ieee80211_device *ieee = ++ (struct ieee80211_device *) _ieee; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ieee->beacon_lock, flags); ++ ieee80211_send_beacon(ieee); ++ spin_unlock_irqrestore(&ieee->beacon_lock, flags); ++} ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ ++inline struct sk_buff *ieee80211_probe_req_with_SSID(struct ieee80211_device *ieee, char *ssid, int len_ssid) ++{ ++ unsigned int len,rate_len; ++ u8 *tag; ++ struct sk_buff *skb; ++ struct ieee80211_probe_request *req; ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ short extMore = 0; ++ if(ieee->ext_patch_ieee80211_probe_req_1) ++ extMore = ieee->ext_patch_ieee80211_probe_req_1(ieee); ++#endif ++ ++ len = len_ssid; ++ ++ rate_len = ieee80211_MFIE_rate_len(ieee); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(!extMore) ++#endif ++ skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) + ++ 2 + len + rate_len); ++#ifdef _RTL8187_EXT_PATCH_ ++ else ++ skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) + ++ 2 + len + rate_len+128); // MESHID + CAP ++#endif ++ ++ if (!skb) ++ return NULL; ++ ++ req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request)); ++ req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); ++ req->header.duration_id = 0; //FIXME: is this OK ? ++ ++ memset(req->header.addr1, 0xff, ETH_ALEN); ++ memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN); ++ memset(req->header.addr3, 0xff, ETH_ALEN); ++ ++ tag = (u8 *) skb_put(skb,len+2+rate_len); ++ ++ *tag++ = MFIE_TYPE_SSID; ++ *tag++ = len; ++ if(len) ++ { ++ memcpy(tag, ssid, len); ++ tag += len; ++ } ++ ++ ieee80211_MFIE_Brate(ieee,&tag); ++ ieee80211_MFIE_Grate(ieee,&tag); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(extMore) ++ ieee->ext_patch_ieee80211_probe_req_2(ieee, skb, tag); ++#endif ++ return skb; ++} ++ ++#endif // _RTL8187_EXT_PATCH_ ++ ++ ++void ieee80211_send_probe(struct ieee80211_device *ieee) ++{ ++ struct sk_buff *skb; ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(ieee->iw_mode == ieee->iw_ext_mode) ++ skb = ieee80211_probe_req_with_SSID(ieee, NULL, 0); ++ else ++#endif ++ skb = ieee80211_probe_req(ieee); ++ if (skb){ ++ softmac_mgmt_xmit(skb, ieee); ++ ieee->softmac_stats.tx_probe_rq++; ++ dev_kfree_skb_any(skb);//edit by thomas ++ } ++} ++ ++void ieee80211_send_probe_requests(struct ieee80211_device *ieee) ++{ ++ if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){ ++ ieee80211_send_probe(ieee); ++ ieee80211_send_probe(ieee); ++ } ++} ++ ++/* this performs syncro scan blocking the caller until all channels ++ * in the allowed channel map has been checked. ++ */ ++void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee) ++{ ++ short ch = 0; ++#ifdef ENABLE_DOT11D ++ u8 channel_map[MAX_CHANNEL_NUMBER+1]; ++ memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1); ++#endif ++ ++ ++ down(&ieee->scan_sem); ++ ++ while(1) ++ { ++ ++ do{ ++ ch++; ++ if (ch > MAX_CHANNEL_NUMBER) ++ goto out; /* scan completed */ ++ ++#ifdef ENABLE_DOT11D ++ }while(!channel_map[ch]); ++#else ++ }while(!ieee->channel_map[ch]); ++#endif ++ ++ //printk("=>current channel is %d\n",ch); ++ ++ /* this fuction can be called in two situations ++ * 1- We have switched to ad-hoc mode and we are ++ * performing a complete syncro scan before conclude ++ * there are no interesting cell and to create a ++ * new one. In this case the link state is ++ * IEEE80211_NOLINK until we found an interesting cell. ++ * If so the ieee8021_new_net, called by the RX path ++ * will set the state to IEEE80211_LINKED, so we stop ++ * scanning ++ * 2- We are linked and the root uses run iwlist scan. ++ * So we switch to IEEE80211_LINKED_SCANNING to remember ++ * that we are still logically linked (not interested in ++ * new network events, despite for updating the net list, ++ * but we are temporarly 'unlinked' as the driver shall ++ * not filter RX frames and the channel is changing. ++ * So the only situation in witch are interested is to check ++ * if the state become LINKED because of the #1 situation ++ */ ++ ++ if (ieee->state == IEEE80211_LINKED) ++ goto out; ++ ++ //printk("---->%s: chan %d\n", __func__, ch); ++ ieee->set_chan(ieee->dev, ch); ++#ifdef ENABLE_DOT11D ++ if(channel_map[ch] == 1) ++#endif ++ { ++ ieee80211_send_probe_requests(ieee); ++ } ++ ++ /* this prevent excessive time wait when we ++ * need to wait for a syncro scan to end.. ++ */ ++ if (ieee->sync_scan_hurryup) ++ goto out; ++ ++ ++ msleep_interruptible_rtl(IEEE80211_SOFTMAC_SCAN_TIME); ++ ++ } ++out: ++ ieee->sync_scan_hurryup = 0; ++ up(&ieee->scan_sem); ++#ifdef ENABLE_DOT11D ++ if(IS_DOT11D_ENABLE(ieee)) ++ DOT11D_ScanComplete(ieee); ++#endif ++ ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ++/* called both by wq with ieee->lock held */ ++void ieee80211_softmac_scan(struct ieee80211_device *ieee) ++{ ++#if 0 ++ short watchdog = 0; ++ do{ ++ ieee->current_network.channel = ++ (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER; ++ if (watchdog++ > MAX_CHANNEL_NUMBER) ++ return; /* no good chans */ ++ ++ }while(!ieee->channel_map[ieee->current_network.channel]); ++#endif ++ ++ schedule_task(&ieee->softmac_scan_wq); ++} ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void ieee80211_softmac_scan_wq(struct work_struct *work) ++{ ++ struct delayed_work *dwork = container_of(work, struct delayed_work, work); ++ struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq); ++#else ++void ieee80211_softmac_scan_wq(struct ieee80211_device *ieee) ++{ ++#endif ++ //static short watchdog = 0; ++ //short watchdog = 0;//lzm move into ieee->scan_watchdog 081215 for roaming ++ u8 channel_bak = ieee->current_network.channel;//lzm for channel+1 ++#ifdef ENABLE_DOT11D ++ u8 channel_map[MAX_CHANNEL_NUMBER+1]; ++ memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1); ++#endif ++ down(&ieee->scan_sem); ++ ++ do{ ++ ieee->current_network.channel = ++ (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER; ++ if (ieee->scan_watchdog++ > MAX_CHANNEL_NUMBER) ++ goto out; /* no good chans */ ++#ifdef ENABLE_DOT11D ++ }while(!channel_map[ieee->current_network.channel]); ++#else ++ }while(!ieee->channel_map[ieee->current_network.channel]); ++#endif ++ ++ if (ieee->scanning == 0 ) ++ goto out; ++ ++ //printk("current channel is %d\n",ieee->current_network.channel); ++ ieee->set_chan(ieee->dev, ieee->current_network.channel); ++#ifdef ENABLE_DOT11D ++ if(channel_map[ieee->current_network.channel] == 1) ++#endif ++ { ++ ieee80211_send_probe_requests(ieee); ++ } ++ ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME); ++#else ++ ieee->scan_timer.expires = jiffies + (IEEE80211_SOFTMAC_SCAN_TIME); ++ if (ieee->scanning == 1) ++ add_timer(&ieee->scan_timer); ++#endif ++ ++ up(&ieee->scan_sem); ++ return; ++out: ++ //printk("%s():Stop scan now\n",__FUNCTION__); ++ ieee->actscanning = false; ++ ieee->scan_watchdog = 0; ++ ieee->scanning = 0; ++ ieee->current_network.channel = channel_bak; ++ up(&ieee->scan_sem); ++#ifdef ENABLE_DOT11D ++ if(IS_DOT11D_ENABLE(ieee)) ++ DOT11D_ScanComplete(ieee); ++#endif ++ ++ return; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ++void ieee80211_softmac_scan_cb(unsigned long _dev) ++{ ++ unsigned long flags; ++ struct ieee80211_device *ieee = (struct ieee80211_device *)_dev; ++ ++ spin_lock_irqsave(&ieee->lock, flags); ++ ieee80211_softmac_scan(ieee); ++ spin_unlock_irqrestore(&ieee->lock, flags); ++} ++#endif ++ ++ ++void ieee80211_beacons_start(struct ieee80211_device *ieee) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ieee->beacon_lock,flags); ++ ++ ieee->beacon_txing = 1; ++ ieee80211_send_beacon(ieee); ++ ++ spin_unlock_irqrestore(&ieee->beacon_lock,flags); ++} ++ ++void ieee80211_beacons_stop(struct ieee80211_device *ieee) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ieee->beacon_lock,flags); ++ ++ ieee->beacon_txing = 0; ++ del_timer_sync(&ieee->beacon_timer); ++ ++ spin_unlock_irqrestore(&ieee->beacon_lock,flags); ++ ++} ++ ++ ++void ieee80211_stop_send_beacons(struct ieee80211_device *ieee) ++{ ++ if(ieee->stop_send_beacons) ++ ieee->stop_send_beacons(ieee->dev); ++ if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS) ++ ieee80211_beacons_stop(ieee); ++} ++ ++ ++void ieee80211_start_send_beacons(struct ieee80211_device *ieee) ++{ ++ if(ieee->start_send_beacons) ++ ieee->start_send_beacons(ieee->dev); ++ if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS) ++ ieee80211_beacons_start(ieee); ++} ++ ++ ++void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee) ++{ ++// unsigned long flags; ++ ++ ieee->sync_scan_hurryup = 1; ++ ++ down(&ieee->scan_sem); ++// spin_lock_irqsave(&ieee->lock, flags); ++ ++ if (ieee->scanning == 1){ ++ //printk("%s():Stop scan now\n",__FUNCTION__); ++ ieee->scanning = 0; ++ //lzm add for softmac_scan_wq can't return from out ++ //example: rcv probe_response ++ ieee->scan_watchdog = 0;//lzm add 081215 for roaming ++ ieee->actscanning = false; ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ cancel_delayed_work(&ieee->softmac_scan_wq); ++#else ++ del_timer_sync(&ieee->scan_timer); ++#endif ++ } ++ ++// spin_unlock_irqrestore(&ieee->lock, flags); ++ up(&ieee->scan_sem); ++} ++ ++void ieee80211_stop_scan(struct ieee80211_device *ieee) ++{ ++ if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) ++ ieee80211_softmac_stop_scan(ieee); ++ else ++ ieee->stop_scan(ieee->dev); ++} ++ ++/* called with ieee->lock held */ ++void ieee80211_start_scan(struct ieee80211_device *ieee) ++{ ++ ieee->actscanning = true; ++#ifdef CONFIG_IPS ++ ieee->ieee80211_ips_leave(ieee->dev); ++#endif ++ ++#ifdef ENABLE_DOT11D ++ if(IS_DOT11D_ENABLE(ieee) ) ++ { ++ if(IS_COUNTRY_IE_VALID(ieee)) ++ { ++ RESET_CIE_WATCHDOG(ieee); ++ } ++ } ++#endif ++ ++ if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){ ++ if (ieee->scanning == 0){ ++ ieee->scanning = 1; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq,0); ++#else ++ ieee80211_softmac_scan(ieee); ++#endif ++ } ++ }else ++ ieee->start_scan(ieee->dev); ++ ++} ++ ++/* called with wx_sem held */ ++void ieee80211_start_scan_syncro(struct ieee80211_device *ieee) ++{ ++ //printk("====>%s()\n", __func__); ++#ifdef CONFIG_IPS ++ ieee->ieee80211_ips_leave(ieee->dev); ++#endif ++ ieee->actscanning = true; ++ ++#ifdef ENABLE_DOT11D ++ if(IS_DOT11D_ENABLE(ieee) ) ++ { ++ if(IS_COUNTRY_IE_VALID(ieee)) ++ { ++ RESET_CIE_WATCHDOG(ieee); ++ } ++ } ++#endif ++ ++ ieee->sync_scan_hurryup = 0; ++ ++ if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) ++ ieee80211_softmac_scan_syncro(ieee); ++ else ++ ieee->scan_syncro(ieee->dev); ++ ++ ieee->actscanning = false; ++ //printk("<====%s()\n", __func__); ++} ++ ++inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon, ++ struct ieee80211_device *ieee, int challengelen) ++{ ++ struct sk_buff *skb; ++ struct ieee80211_authentication *auth; ++ ++ skb = dev_alloc_skb(sizeof(struct ieee80211_authentication) + challengelen); ++ ++ if (!skb) return NULL; ++ ++ auth = (struct ieee80211_authentication *) ++ skb_put(skb, sizeof(struct ieee80211_authentication)); ++ ++ auth->header.frame_ctl = IEEE80211_STYPE_AUTH; ++ if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP; ++ ++ auth->header.duration_id = 0x013a; //FIXME ++ ++ memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN); ++ memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); ++ memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN); ++ ++ auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; ++ ++ auth->transaction = cpu_to_le16(ieee->associate_seq); ++ ieee->associate_seq++; ++ ++ auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS); ++ ++ return skb; ++ ++} ++ ++u8 WPA_OUI[3] = {0x00, 0x50, 0xf2}; ++ ++static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest) ++{ ++ u8 *tag; ++ int beacon_size; ++ struct ieee80211_probe_response *beacon_buf; ++ struct sk_buff *skb; ++ int encrypt; ++ int atim_len,erp_len; ++ struct ieee80211_crypt_data* crypt; ++ ++ char *ssid = ieee->current_network.ssid; ++ int ssid_len = ieee->current_network.ssid_len; ++ int rate_len = ieee->current_network.rates_len+2; ++ int rate_ex_len = ieee->current_network.rates_ex_len; ++ ++ int wpa_ie_len = 0, wpa_type=0; ++ if(rate_ex_len > 0) rate_ex_len+=2; ++ ++ if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS) ++ atim_len = 4; ++ else ++ atim_len = 0; ++ ++ if(ieee80211_is_54g(ieee->current_network)) ++ erp_len = 3; ++ else ++ erp_len = 0; ++ if (ieee->wpa_enabled) ++ { ++ // printk("hoho wpa_enalbe\n"); ++ wpa_ie_len = ieee->wpa_ie_len; //24-2 ++ } ++ beacon_size = sizeof(struct ieee80211_probe_response)+ ++ ssid_len ++ +3 //channel ++ +rate_len ++ +rate_ex_len ++ +atim_len ++ +erp_len ++ +wpa_ie_len; ++ ++ skb = dev_alloc_skb(beacon_size); ++ ++ if (!skb) ++ return NULL; ++ ++ beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, beacon_size); ++ ++ memcpy (beacon_buf->header.addr1, dest,ETH_ALEN); ++ memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN); ++ memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN); ++ ++ beacon_buf->header.duration_id = 0; //FIXME ++ beacon_buf->beacon_interval = ++ cpu_to_le16(ieee->current_network.beacon_interval); ++ beacon_buf->capability = ++ cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS); ++ ++ if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT)) ++ cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT)); ++#ifdef _RTL8187_EXT_PATCH_ ++{ ++/* struct ieee80211_crypt_data_list* cryptlist = ieee->cryptlist[1]; ++ u8 i = cryptlist->used; ++ crypt = cryptlist ->crypt[ieee->tx_keyidx]; ++*/ ++ crypt = ieee->cryptlist[0]->crypt[ieee->tx_keyidx]; ++} ++#else ++ ++ crypt = ieee->crypt[ieee->tx_keyidx]; ++#endif ++ if (crypt) ++ wpa_type = strcmp(crypt->ops->name, "TKIP"); ++ ++ ++ encrypt = ieee->host_encrypt && crypt && crypt->ops && ++ ((0 == strcmp(crypt->ops->name, "WEP")||wpa_ie_len)); ++ ++ if (encrypt) ++ beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); ++ ++ ++ beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP); ++ ++ beacon_buf->info_element.id = MFIE_TYPE_SSID; ++ beacon_buf->info_element.len = ssid_len; ++ ++ tag = (u8*) beacon_buf->info_element.data; ++ ++ memcpy(tag, ssid, ssid_len); ++ ++ tag += ssid_len; ++ ++ *(tag++) = MFIE_TYPE_RATES; ++ *(tag++) = rate_len-2; ++ memcpy(tag,ieee->current_network.rates,rate_len-2); ++ tag+=rate_len-2; ++ ++ *(tag++) = MFIE_TYPE_DS_SET; ++ *(tag++) = 1; ++ *(tag++) = ieee->current_network.channel; ++ ++ if(atim_len){ ++ u16 val16; ++ *(tag++) = MFIE_TYPE_IBSS_SET; ++ *(tag++) = 2; ++ val16 = cpu_to_le16(ieee->current_network.atim_window); ++ //*((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window); ++ memcpy((u8 *)tag,(u8 *)&val16,2); ++ tag+=2; ++ } ++ ++ if(erp_len){ ++ *(tag++) = MFIE_TYPE_ERP; ++ *(tag++) = 1; ++ *(tag++) = 0; ++ } ++ ++ if(rate_ex_len){ ++ *(tag++) = MFIE_TYPE_RATES_EX; ++ *(tag++) = rate_ex_len-2; ++ memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2); ++ tag+=rate_ex_len-2; ++ } ++ if (wpa_ie_len) ++ { ++#if 0 ++ *(tag++) = 0xdd; ++ *(tag++) = wpa_ie_len-2; ++ memcpy(tag, WPA_OUI, 3); ++ tag += 3; ++ *(tag++) = 1; ++ *(tag++) = 1; ++ *(tag++) = 0; ++ ++ memcpy(tag, WPA_OUI, 3); ++ tag += 3; ++ *(tag++) = wpa_type ? 4:2; ++ *(tag++) = 1; ++ *(tag++) = 0; ++ ++ ++ memcpy(tag, WPA_OUI, 3); ++ tag += 3; ++ *(tag++) = wpa_type ? 4:0; ++ *(tag++) = 1; ++ *(tag++) = 0; ++ ++ memcpy(tag, WPA_OUI, 3); ++ tag += 3; ++ *(tag++) = 0; ++#else ++ if (ieee->iw_mode == IW_MODE_ADHOC) ++ {//as Windows will set pairwise key same as the group key which is not allowed in Linux, so set this for IOT issue. WB 2008.07.07 ++ memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4); ++ } ++ ++ memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); ++ ++#endif ++ } ++ ++ ++ skb->dev = ieee->dev; ++ return skb; ++} ++ ++ ++#ifdef _RTL8187_EXT_PATCH_ ++struct sk_buff* ieee80211_ext_probe_resp_by_net(struct ieee80211_device *ieee, u8 *dest, struct ieee80211_network *net) ++{ ++ u8 *tag; ++ int beacon_size; ++ struct ieee80211_probe_response *beacon_buf; ++ struct sk_buff *skb; ++ int encrypt; ++ int atim_len,erp_len; ++ struct ieee80211_crypt_data* crypt; ++ u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff}; ++ ++ char *ssid = net->ssid; ++ int ssid_len = net->ssid_len; ++ ++ int rate_len = ieee->current_network.rates_len+2; ++ int rate_ex_len = ieee->current_network.rates_ex_len; ++ int wpa_ie_len = 0, wpa_type=0; ++ if(rate_ex_len > 0) rate_ex_len+=2; ++ ++ if( ieee->meshScanMode&4) ++ ieee->current_network.channel = ieee->ext_patch_ieee80211_ext_stop_scan_wq_set_channel(ieee); ++ if( ieee->meshScanMode&6) ++ { ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ queue_work(ieee->wq, &ieee->ext_stop_scan_wq); ++#else ++ schedule_task(&ieee->ext_stop_scan_wq); ++#endif ++ } ++ if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS) // use current_network here ++ atim_len = 4; ++ else ++ atim_len = 0; ++ ++ if(ieee80211_is_54g(*net)) ++ erp_len = 3; ++ else ++ erp_len = 0; ++ ++ if (ieee->wpa_enabled &&(ieee->iw_ext_mode==ieee->iw_mode)) ++ { ++// printk("hoho wpa_enalbe\n"); ++ wpa_ie_len = ieee->wpa_ie_len; //24-2 ++ } ++ ++ beacon_size = sizeof(struct ieee80211_probe_response)+ ++ ssid_len ++ +3 //channel ++ +rate_len ++ +rate_ex_len ++ +atim_len ++ +erp_len ++ +wpa_ie_len; ++//b ++ skb = dev_alloc_skb(beacon_size+196); ++ ++ if (!skb) ++ return NULL; ++ ++ beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, beacon_size); ++ ++ memcpy (beacon_buf->header.addr1, dest,ETH_ALEN); ++ memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN); ++ memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN); ++ ++ beacon_buf->header.duration_id = 0; //FIXME ++ ++ beacon_buf->beacon_interval = ++ cpu_to_le16(ieee->current_network.beacon_interval); // use current_network here ++ beacon_buf->capability = ++ cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS); ++ ++ if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT)) ++ cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT)); ++#ifdef _RTL8187_EXT_PATCH_ ++ ++ crypt = ieee->cryptlist[0]->crypt[ieee->tx_keyidx]; ++#else ++ ++ crypt = ieee->crypt[ieee->tx_keyidx]; ++#endif ++ ++// crypt = ieee->crypt[ieee->tx_keyidx]; ++ if (crypt) ++ wpa_type = strcmp(crypt->ops->name, "TKIP"); ++ ++ encrypt = ieee->host_encrypt && crypt && crypt->ops && ++ ((0 == strcmp(crypt->ops->name, "WEP")||wpa_ie_len)); ++ ++ if (encrypt) ++ beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); ++ ++ ++ beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP); ++ ++ beacon_buf->info_element.id = MFIE_TYPE_SSID; ++ beacon_buf->info_element.len = ssid_len; ++ ++ tag = (u8*) beacon_buf->info_element.data; ++ ++ // brocad cast / probe rsp ++ if(memcmp(dest, broadcast_addr, ETH_ALEN )) ++ memcpy(tag, ssid, ssid_len); ++ else ++ ssid_len=0; ++ ++ tag += ssid_len; ++ ++//get_bssrate_set(priv, _SUPPORTEDRATES_IE_, &pbssrate, &bssrate_len); ++//pbuf = set_ie(pbuf, _SUPPORTEDRATES_IE_, bssrate_len, pbssrate, &frlen); ++ ++ *(tag++) = MFIE_TYPE_RATES; ++ *(tag++) = rate_len-2; ++ memcpy(tag,ieee->current_network.rates,rate_len-2); ++ tag+=rate_len-2; ++ ++ *(tag++) = MFIE_TYPE_DS_SET; ++ *(tag++) = 1; ++ *(tag++) = ieee->current_network.channel; // use current_network here ++ ++ ++ if(atim_len){ ++ *(tag++) = MFIE_TYPE_IBSS_SET; ++ *(tag++) = 2; ++ *((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window); // use current_network here ++ tag+=2; ++ } ++ ++ if(erp_len){ ++ *(tag++) = MFIE_TYPE_ERP; ++ *(tag++) = 1; ++ *(tag++) = 0; ++ } ++ ++ if(rate_ex_len){ ++ *(tag++) = MFIE_TYPE_RATES_EX; ++ *(tag++) = rate_ex_len-2; ++ memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2); ++ tag+=rate_ex_len-2; ++ } ++ ++ if (wpa_ie_len) ++ { ++#if 0 ++ *(tag++) = 0xdd; ++ *(tag++) = wpa_ie_len-2; ++ memcpy(tag, WPA_OUI, 3); ++ tag += 3; ++ *(tag++) = 1; ++ *(tag++) = 1; ++ *(tag++) = 0; ++ ++ memcpy(tag, WPA_OUI, 3); ++ tag += 3; ++ *(tag++) = wpa_type ? 4:2; ++ *(tag++) = 1; ++ *(tag++) = 0; ++ ++ ++ memcpy(tag, WPA_OUI, 3); ++ tag += 3; ++ *(tag++) = wpa_type ? 4:0; ++ *(tag++) = 1; ++ *(tag++) = 0; ++ ++ memcpy(tag, WPA_OUI, 3); ++ tag += 3; ++ *(tag++) = 0; ++#else ++ memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); ++#endif ++ } ++ ++ ++ skb->dev = ieee->dev; ++ return skb; ++} ++#endif // _RTL8187_EXT_PATCH_ ++ ++ ++struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest) ++{ ++ struct sk_buff *skb; ++ u8* tag; ++ ++ struct ieee80211_crypt_data* crypt; ++ struct ieee80211_assoc_response_frame *assoc; ++ short encrypt; ++ ++ unsigned int rate_len = ieee80211_MFIE_rate_len(ieee); ++ int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len; ++ ++ skb = dev_alloc_skb(len); ++ ++ if (!skb) ++ return NULL; ++ ++ assoc = (struct ieee80211_assoc_response_frame *) ++ skb_put(skb,sizeof(struct ieee80211_assoc_response_frame)); ++ ++ assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP); ++ memcpy(assoc->header.addr1, dest,ETH_ALEN); ++ memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN); ++ memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN); ++ assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ? ++ WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS); ++ ++ ++ if(ieee->short_slot) ++ assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); ++ ++ if (ieee->host_encrypt){ ++#ifdef _RTL8187_EXT_PATCH_ ++ crypt = ieee->cryptlist[0]->crypt[ieee->tx_keyidx]; ++#else ++ crypt = ieee->crypt[ieee->tx_keyidx]; ++#endif ++ } ++ else crypt = NULL; ++ ++ encrypt = ( crypt && crypt->ops); ++ ++ if (encrypt) ++ assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); ++ ++ assoc->status = 0; ++ assoc->aid = cpu_to_le16(ieee->assoc_id); ++ if (ieee->assoc_id == 0x2007) ieee->assoc_id=0; ++ else ieee->assoc_id++; ++ ++ tag = (u8*) skb_put(skb, rate_len); ++ ++ ieee80211_MFIE_Brate(ieee, &tag); ++ ieee80211_MFIE_Grate(ieee, &tag); ++ ++ return skb; ++} ++ ++struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest) ++{ ++ struct sk_buff *skb; ++ struct ieee80211_authentication *auth; ++ ++ skb = dev_alloc_skb(sizeof(struct ieee80211_authentication)+1); ++ ++ if (!skb) ++ return NULL; ++ ++ skb->len = sizeof(struct ieee80211_authentication); ++ ++ auth = (struct ieee80211_authentication *)skb->data; ++ ++ auth->status = cpu_to_le16(status); ++ auth->transaction = cpu_to_le16(2); ++ auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(ieee->iw_mode == ieee->iw_ext_mode) ++ memcpy(auth->header.addr3, dest, ETH_ALEN); ++#else ++ memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN); ++#endif ++ memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); ++ memcpy(auth->header.addr1, dest, ETH_ALEN); ++ auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH); ++ return skb; ++ ++ ++} ++ ++struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr) ++{ ++ struct sk_buff *skb; ++ struct ieee80211_hdr_3addr* hdr; ++ ++ skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr)); ++ ++ if (!skb) ++ return NULL; ++ ++ hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr)); ++ ++ memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN); ++ memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN); ++ memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN); ++ ++ hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | ++ IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS | ++ (pwr ? IEEE80211_FCTL_PM:0)); ++ ++ return skb; ++ ++ ++} ++ ++ ++void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest) ++{ ++ struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest); ++ ++ if (buf){ ++ softmac_mgmt_xmit(buf, ieee); ++ dev_kfree_skb_any(buf);//edit by thomas ++ } ++} ++ ++ ++void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest) ++{ ++ struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest); ++ ++ if (buf){ ++ softmac_mgmt_xmit(buf, ieee); ++ dev_kfree_skb_any(buf);//edit by thomas ++ } ++} ++ ++ ++void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest) ++{ ++ ++ struct sk_buff *buf = ieee80211_probe_resp(ieee, dest); ++ ++ if (buf) { ++ softmac_mgmt_xmit(buf, ieee); ++ dev_kfree_skb_any(buf);//edit by thomas ++ } ++} ++ ++ ++inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee) ++{ ++ struct sk_buff *skb; ++ ++ struct ieee80211_assoc_request_frame *hdr; ++ u8 *tag; ++ //int i; ++ unsigned int wpa_len = beacon->wpa_ie_len; ++#if 1 ++ // for testing purpose ++ unsigned int rsn_len = beacon->rsn_ie_len; ++#else ++ unsigned int rsn_len = beacon->rsn_ie_len - 4; ++#endif ++ unsigned int rate_len = ieee80211_MFIE_rate_len(ieee); ++ unsigned int wmm_info_len = beacon->QoS_Enable?9:0; ++#ifdef THOMAS_TURBO ++ unsigned int turbo_info_len = beacon->Turbo_Enable?9:0; ++#endif ++ ++ u8 encry_proto = ieee->wpax_type_notify & 0xff; ++ ++ ++ int len = 0; ++ ++ //[0] Notify type of encryption: WPA/WPA2 ++ //[1] pair wise type ++ //[2] authen type ++ if(ieee->wpax_type_set) { ++ if (IEEE_PROTO_WPA == encry_proto) { ++ rsn_len = 0; ++ } else if (IEEE_PROTO_RSN == encry_proto) { ++ wpa_len = 0; ++ } ++ } ++#ifdef THOMAS_TURBO ++ len = sizeof(struct ieee80211_assoc_request_frame)+ ++ + beacon->ssid_len//essid tagged val ++ + rate_len//rates tagged val ++ + wpa_len ++ + rsn_len ++ + wmm_info_len ++ + turbo_info_len; ++#else ++ len = sizeof(struct ieee80211_assoc_request_frame)+ ++ + beacon->ssid_len//essid tagged val ++ + rate_len//rates tagged val ++ + wpa_len ++ + rsn_len ++ + wmm_info_len; ++#endif ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(ieee->iw_mode == ieee->iw_ext_mode) ++ skb = dev_alloc_skb(len+256); // stanley ++ else ++#endif ++ skb = dev_alloc_skb(len); ++ ++ if (!skb) ++ return NULL; ++ ++ hdr = (struct ieee80211_assoc_request_frame *) ++ skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)); ++ ++ ++ hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ; ++ hdr->header.duration_id= 37; //FIXME ++ memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN); ++ memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN); ++ memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN); ++ memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John ++ ++ hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS); ++ if (beacon->capability & WLAN_CAPABILITY_PRIVACY ) ++ hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); ++ ++ if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE ) ++ hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); ++ ++ if(ieee->short_slot) ++ hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_association_req_1) ++ ieee->ext_patch_ieee80211_association_req_1(hdr); ++#endif ++ ++ hdr->listen_interval = 0xa; //FIXME ++ ++ hdr->info_element.id = MFIE_TYPE_SSID; ++ ++ hdr->info_element.len = beacon->ssid_len; ++ tag = skb_put(skb, beacon->ssid_len); ++ memcpy(tag, beacon->ssid, beacon->ssid_len); ++ ++ tag = skb_put(skb, rate_len); ++ ++ ieee80211_MFIE_Brate(ieee, &tag); ++ ieee80211_MFIE_Grate(ieee, &tag); ++ ++ //add rsn==0 condition for ap's mix security mode(wpa+wpa2), john2007.8.9 ++ //choose AES encryption as default algorithm while using mixed mode ++#if 0 ++ if(rsn_len == 0){ ++ ++ tag = skb_put(skb,wpa_len); ++ ++ if(wpa_len) { ++ ++ ++ //{add by david. 2006.8.31 ++ //fix linksys compatibility bug ++ //} ++ if(wpa_len > 24) {//22+2, mean include the capability ++ beacon->wpa_ie[wpa_len - 2] = 0; ++ } ++ //multicast cipher OUI ++ if( beacon->wpa_ie[11]==0x2 ){ //0x0050f202 is the oui of tkip ++ ieee->broadcast_key_type = KEY_TYPE_TKIP; ++ } ++ else if( beacon->wpa_ie[11]==0x4 ){//0x0050f204 is the oui of ccmp ++ ieee->broadcast_key_type = KEY_TYPE_CCMP; ++ } ++ //unicast cipher OUI ++ if( beacon->wpa_ie[14]==0 ++ && beacon->wpa_ie[15]==0x50 ++ && beacon->wpa_ie[16]==0xf2 ++ && beacon->wpa_ie[17]==0x2 ){ //0x0050f202 is the oui of tkip ++ ieee->pairwise_key_type = KEY_TYPE_TKIP; ++ } ++ ++ else if( beacon->wpa_ie[14]==0 ++ && beacon->wpa_ie[15]==0x50 ++ && beacon->wpa_ie[16]==0xf2 ++ && beacon->wpa_ie[17]==0x4 ){//0x0050f204 is the oui of ccmp ++ ieee->pairwise_key_type = KEY_TYPE_CCMP; ++ } ++ //indicate the wpa_ie content to WPA_SUPPLICANT ++ buff = kmalloc(IW_CUSTOM_MAX, GFP_ATOMIC); ++ memset(buff, 0, IW_CUSTOM_MAX); ++ p=buff; ++ p += sprintf(p, "ASSOCINFO(ReqIEs="); ++ for(i=0;iwpa_ie[i]); ++ } ++ p += sprintf(p, ")"); ++ memset(&wrqu, 0, sizeof(wrqu) ); ++ wrqu.data.length = p - buff; ++ ++ wireless_send_event(dev, IWEVCUSTOM, &wrqu, buff); ++ memcpy(tag,beacon->wpa_ie,wpa_len); ++ } ++ ++ } ++ ++ if(rsn_len > 22) { ++ ++ if( beacon->rsn_ie[4]==0x0 && ++ beacon->rsn_ie[5]==0xf && ++ beacon->rsn_ie[6]==0xac){ ++ ++ switch(beacon->rsn_ie[7]){ ++ case 0x1: ++ ieee->broadcast_key_type = KEY_TYPE_WEP40; ++ break; ++ case 0x2: ++ ieee->broadcast_key_type = KEY_TYPE_TKIP; ++ break; ++ case 0x4: ++ ieee->broadcast_key_type = KEY_TYPE_CCMP; ++ break; ++ case 0x5: ++ ieee->broadcast_key_type = KEY_TYPE_WEP104; ++ break; ++ default: ++ printk("fault suite type in RSN broadcast key\n"); ++ break; ++ } ++ } ++ ++ if( beacon->rsn_ie[10]==0x0 && ++ beacon->rsn_ie[11]==0xf && ++ beacon->rsn_ie[12]==0xac){ ++ if(beacon->rsn_ie[8]==1){//not mixed mode ++ switch(beacon->rsn_ie[13]){ ++ case 0x2: ++ ieee->pairwise_key_type = KEY_TYPE_TKIP; ++ break; ++ case 0x4: ++ ieee->pairwise_key_type = KEY_TYPE_CCMP; ++ break; ++ default: ++ printk("fault suite type in RSN pairwise key\n"); ++ break; ++ } ++ } ++ else if(beacon->rsn_ie[8]==2){//mixed mode ++ ieee->pairwise_key_type = KEY_TYPE_CCMP; ++ } ++ } ++ ++ ++ ++ tag = skb_put(skb,22); ++ memcpy(tag,(beacon->rsn_ie + info_addr),8); ++ tag[1] = 20; ++ tag += 8; ++ info_addr += 8; ++ ++ spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags); ++ for (i = 0; i < 2; i++) { ++ tag[0] = 1; ++ tag[1] = 0; ++ tag += 2; ++ suite_count = beacon->rsn_ie[info_addr] + \ ++ (beacon->rsn_ie[info_addr + 1] << 8); ++ info_addr += 2; ++ if(1 == suite_count) { ++ memcpy(tag,(beacon->rsn_ie + info_addr),4); ++ info_addr += 4; ++ } else { ++ // if the wpax_type_notify has been set by the application, ++ // just use it, otherwise just use the default one. ++ if(ieee->wpax_type_set) { ++ suit_select = ((0 == i) ? pairwise_type:authen_type)&0x0f ; ++ memcpy(tag,rsn_authen_cipher_suite[suit_select],4); ++ } else { ++ //default set as ccmp, or none authentication ++ if(i == 0) { ++ memcpy(tag,rsn_authen_cipher_suite[4],4); ++ } else { ++ memcpy(tag,rsn_authen_cipher_suite[2],4); ++ } ++ ++ } ++ ++ info_addr += (suite_count * 4); ++ } ++ tag += 4; ++ } ++ spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags); ++ ++ tag[0] = 0; ++ tag[1] = beacon->rsn_ie[info_addr+1]; ++ ++ ++ ++ } else { ++ tag = skb_put(skb,rsn_len); ++ if(rsn_len) { ++ ++ ++ if( beacon->rsn_ie[4]==0x0 && ++ beacon->rsn_ie[5]==0xf && ++ beacon->rsn_ie[6]==0xac){ ++ switch(beacon->rsn_ie[7]){ ++ case 0x1: ++ ieee->broadcast_key_type = KEY_TYPE_WEP40; ++ break; ++ case 0x2: ++ ieee->broadcast_key_type = KEY_TYPE_TKIP; ++ break; ++ case 0x4: ++ ieee->broadcast_key_type = KEY_TYPE_CCMP; ++ break; ++ case 0x5: ++ ieee->broadcast_key_type = KEY_TYPE_WEP104; ++ break; ++ default: ++ printk("fault suite type in RSN broadcast key\n"); ++ break; ++ } ++ } ++ if( beacon->rsn_ie[10]==0x0 && ++ beacon->rsn_ie[11]==0xf && ++ beacon->rsn_ie[12]==0xac){ ++ if(beacon->rsn_ie[8]==1){//not mixed mode ++ switch(beacon->rsn_ie[13]){ ++ case 0x2: ++ ieee->pairwise_key_type = KEY_TYPE_TKIP; ++ break; ++ case 0x4: ++ ieee->pairwise_key_type = KEY_TYPE_CCMP; ++ break; ++ default: ++ printk("fault suite type in RSN pairwise key\n"); ++ break; ++ } ++ ++ } ++ else if(beacon->rsn_ie[8]==2){//mixed mode ++ ieee->pairwise_key_type = KEY_TYPE_CCMP; ++ } ++ } ++ ++ ++ beacon->rsn_ie[rsn_len - 2] = 0; ++ memcpy(tag,beacon->rsn_ie,rsn_len); ++ } ++ } ++#else ++ if (ieee->wpa_ie){ ++ tag = skb_put(skb,ieee->wpa_ie_len); ++ memcpy(tag,ieee->wpa_ie,ieee->wpa_ie_len); ++ } ++#endif ++ tag = skb_put(skb,wmm_info_len); ++ if(wmm_info_len) { ++ ieee80211_WMM_Info(ieee, &tag); ++ } ++#ifdef THOMAS_TURBO ++ tag = skb_put(skb,turbo_info_len); ++ if(turbo_info_len) { ++ ieee80211_TURBO_Info(ieee, &tag); ++ } ++#endif ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_association_req_2) ++ ieee->ext_patch_ieee80211_association_req_2(ieee, beacon, skb); ++#endif ++ ++ return skb; ++} ++ ++void ieee80211_associate_abort(struct ieee80211_device *ieee) ++{ ++ ++ unsigned long flags; ++ spin_lock_irqsave(&ieee->lock, flags); ++ ++ ieee->associate_seq++; ++ ++ /* don't scan, and avoid to have the RX path possibily ++ * try again to associate. Even do not react to AUTH or ++ * ASSOC response. Just wait for the retry wq to be scheduled. ++ * Here we will check if there are good nets to associate ++ * with, so we retry or just get back to NO_LINK and scanning ++ */ ++ if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){ ++ IEEE80211_DEBUG_MGMT("Authentication failed\n"); ++ ieee->softmac_stats.no_auth_rs++; ++ }else{ ++ IEEE80211_DEBUG_MGMT("Association failed\n"); ++ ieee->softmac_stats.no_ass_rs++; ++ } ++ ++ ieee->state = IEEE80211_ASSOCIATING_RETRY; ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \ ++ IEEE80211_SOFTMAC_ASSOC_RETRY_TIME); ++#else ++ schedule_task(&ieee->associate_retry_wq); ++#endif ++ ++ spin_unlock_irqrestore(&ieee->lock, flags); ++} ++ ++void ieee80211_associate_abort_cb(unsigned long dev) ++{ ++ ieee80211_associate_abort((struct ieee80211_device *) dev); ++} ++ ++ ++void ieee80211_associate_step1(struct ieee80211_device *ieee) ++{ ++ struct ieee80211_network *beacon = &ieee->current_network; ++ struct sk_buff *skb; ++ ++ IEEE80211_DEBUG_MGMT("Stopping scan\n"); ++ ++ ieee->softmac_stats.tx_auth_rq++; ++ skb=ieee80211_authentication_req(beacon, ieee, 0); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(ieee->iw_mode == ieee->iw_ext_mode ) { ++ if(skb) ++ softmac_mgmt_xmit(skb, ieee); ++ return; ++ }else ++#endif ++ if (!skb) ++ ieee80211_associate_abort(ieee); ++ else{ ++ ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ; ++ IEEE80211_DEBUG_MGMT("Sending authentication request\n"); ++ //printk(KERN_WARNING "Sending authentication request\n"); ++ softmac_mgmt_xmit(skb, ieee); ++ //BUGON when you try to add_timer twice, using mod_timer may be better, john0709 ++ if(!timer_pending(&ieee->associate_timer)){ ++ ieee->associate_timer.expires = jiffies + (HZ / 2); ++ add_timer(&ieee->associate_timer); ++ } ++ dev_kfree_skb_any(skb);//edit by thomas ++ } ++} ++ ++void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) ++{ ++ u8 *c; ++ struct sk_buff *skb; ++ struct ieee80211_network *beacon = &ieee->current_network; ++// int hlen = sizeof(struct ieee80211_authentication); ++ ++ ieee->associate_seq++; ++ ieee->softmac_stats.tx_auth_rq++; ++ ++ skb = ieee80211_authentication_req(beacon, ieee, chlen+2); ++ if (!skb) ++ ieee80211_associate_abort(ieee); ++ else{ ++ c = skb_put(skb, chlen+2); ++ *(c++) = MFIE_TYPE_CHALLENGE; ++ *(c++) = chlen; ++ memcpy(c, challenge, chlen); ++ ++ IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n"); ++ ++ ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr )); ++ ++ softmac_mgmt_xmit(skb, ieee); ++ ++ if(!timer_pending(&ieee->associate_timer)){ ++ ieee->associate_timer.expires = jiffies + (HZ / 2); ++ add_timer(&ieee->associate_timer); ++ } ++ dev_kfree_skb_any(skb);//edit by thomas ++ } ++ kfree(challenge); ++} ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ ++// based on ieee80211_assoc_resp ++struct sk_buff* ieee80211_assoc_resp_by_net(struct ieee80211_device *ieee, u8 *dest, unsigned short status, struct ieee80211_network *pstat, int pkt_type) ++{ ++ struct sk_buff *skb; ++ u8* tag; ++ ++ struct ieee80211_crypt_data* crypt; ++ struct ieee80211_assoc_response_frame *assoc; ++ short encrypt; ++ ++ unsigned int rate_len = ieee80211_MFIE_rate_len(ieee); ++ int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len; ++ ++ if(ieee->iw_mode == ieee->iw_ext_mode) ++ skb = dev_alloc_skb(len+256); // stanley ++ else ++ skb = dev_alloc_skb(len); ++ ++ if (!skb) ++ return NULL; ++ ++ assoc = (struct ieee80211_assoc_response_frame *) ++ skb_put(skb,sizeof(struct ieee80211_assoc_response_frame)); ++ ++ assoc->header.frame_ctl = cpu_to_le16(pkt_type); ++ ++ memcpy(assoc->header.addr1, dest,ETH_ALEN); ++ memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN); ++ memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN); ++ assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ? ++ WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS); ++ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_assoc_resp_by_net_1) ++ ieee->ext_patch_ieee80211_assoc_resp_by_net_1(assoc); ++ ++ if(ieee->short_slot) ++ assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); ++ ++ if (ieee->host_encrypt) ++#ifdef _RTL8187_EXT_PATCH_ ++ crypt = ieee->cryptlist[0]->crypt[ieee->tx_keyidx]; ++#else ++ crypt = ieee->crypt[ieee->tx_keyidx]; ++#endif ++ ++ else crypt = NULL; ++ ++ encrypt = ( crypt && crypt->ops); ++ ++ if (encrypt) ++ assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); ++ ++ assoc->status = 0; ++ assoc->aid = cpu_to_le16(ieee->assoc_id); ++ if (ieee->assoc_id == 0x2007) ieee->assoc_id=0; ++ else ieee->assoc_id++; ++ ++ assoc->info_element.id = 230; // Stanley, an unused id (just a hot fix) ++ assoc->info_element.len = 0; ++ ++ tag = (u8*) skb_put(skb, rate_len); ++ ++ ieee80211_MFIE_Brate(ieee, &tag); ++ ieee80211_MFIE_Grate(ieee, &tag); ++ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_assoc_resp_by_net_2) ++ ieee->ext_patch_ieee80211_assoc_resp_by_net_2(ieee, pstat, pkt_type, skb); ++ ++ return skb; ++} ++ ++// based on ieee80211_resp_to_assoc_rq ++void ieee80211_ext_issue_assoc_rsp(struct ieee80211_device *ieee, u8 *dest, unsigned short status, struct ieee80211_network *pstat, int pkt_type) ++{ ++ struct sk_buff *buf = ieee80211_assoc_resp_by_net(ieee, dest, status, pstat, pkt_type); ++ ++ if (buf) ++ softmac_mgmt_xmit(buf, ieee); ++} ++ ++// based on ieee80211_associate_step2 ++void ieee80211_ext_issue_assoc_req(struct ieee80211_device *ieee, struct ieee80211_network *pstat) ++{ ++ ++ struct sk_buff* skb; ++ ++ // printk("@@@@@ ieee80211_ext_issue_assoc_req on channel: %d\n", ieee->current_network.channel); ++ ++ ieee->softmac_stats.tx_ass_rq++; ++ skb=ieee80211_association_req(pstat, ieee); ++ if (skb) ++ softmac_mgmt_xmit(skb, ieee); ++} ++ ++void ieee80211_ext_issue_disassoc(struct ieee80211_device *ieee, struct ieee80211_network *pstat, int reason, unsigned char extReason) ++{ ++ // do nothing ++ // printk("@@@@@ ieee80211_ext_issue_disassoc\n"); ++ return; ++} ++#endif // _RTL8187_EXT_PATCH_ ++ ++void ieee80211_associate_step2(struct ieee80211_device *ieee) ++{ ++ struct sk_buff* skb; ++ struct ieee80211_network *beacon = &ieee->current_network; ++ ++// del_timer_sync(&ieee->associate_timer); ++ ++ IEEE80211_DEBUG_MGMT("Sending association request\n"); ++ ++ ieee->softmac_stats.tx_ass_rq++; ++ skb=ieee80211_association_req(beacon, ieee); ++ if (!skb) ++ ieee80211_associate_abort(ieee); ++ else{ ++ softmac_mgmt_xmit(skb, ieee); ++ if(!timer_pending(&ieee->associate_timer)){ ++ ieee->associate_timer.expires = jiffies + (HZ / 2); ++ add_timer(&ieee->associate_timer); ++ } ++ dev_kfree_skb_any(skb);//edit by thomas ++ } ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void ieee80211_associate_complete_wq(struct work_struct *work) ++{ ++ struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq); ++#else ++void ieee80211_associate_complete_wq(struct ieee80211_device *ieee) ++{ ++#endif ++ printk(KERN_INFO "Associated successfully\n"); ++ if(ieee80211_is_54g(ieee->current_network) && ++ (ieee->modulation & IEEE80211_OFDM_MODULATION)){ ++ ++ ieee->rate = 540; ++ printk(KERN_INFO"Using G rates\n"); ++ }else{ ++ ieee->rate = 110; ++ printk(KERN_INFO"Using B rates\n"); ++ } ++ ++//by lizhaoming for LED LINK ++#ifdef LED_SHIN ++ { ++ struct net_device *dev = ieee->dev; ++ ieee->ieee80211_led_contorl(dev, LED_CTL_LINK); ++ } ++#endif ++ ++ ieee->link_change(ieee->dev); ++ notify_wx_assoc_event(ieee); ++ if (ieee->data_hard_resume) ++ ieee->data_hard_resume(ieee->dev); ++ netif_carrier_on(ieee->dev); ++} ++ ++void ieee80211_associate_complete(struct ieee80211_device *ieee) ++{ ++ int i; ++// struct net_device *dev = ieee->dev; ++ del_timer_sync(&ieee->associate_timer); ++ ++ for(i = 0; i < 6; i++) { ++// ieee->seq_ctrl[i] = 0; ++ } ++ ieee->state = IEEE80211_LINKED; ++ IEEE80211_DEBUG_MGMT("Successfully associated\n"); ++ ++ //by lizhaoming for LED LINK ++ //ieee->ieee80211_led_contorl(dev, LED_CTL_LINK); ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ queue_work(ieee->wq, &ieee->associate_complete_wq); ++#else ++ schedule_task(&ieee->associate_complete_wq); ++#endif ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void ieee80211_associate_procedure_wq(struct work_struct *work) ++{ ++ struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq); ++#else ++void ieee80211_associate_procedure_wq(struct ieee80211_device *ieee) ++{ ++#endif ++ ieee->sync_scan_hurryup = 1; ++ down(&ieee->wx_sem); ++ ++ if (ieee->data_hard_stop) ++ ieee->data_hard_stop(ieee->dev); ++ ++ ieee80211_stop_scan(ieee); ++ //printk("=======>%s set chan:%d\n", __func__, ieee->current_network.channel); ++ ieee->set_chan(ieee->dev, ieee->current_network.channel); ++ ++ ieee->associate_seq = 1; ++ ieee80211_associate_step1(ieee); ++ ++ up(&ieee->wx_sem); ++} ++#ifdef _RTL8187_EXT_PATCH_ ++// based on ieee80211_associate_procedure_wq ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++void ieee80211_ext_stop_scan_wq(struct work_struct *work) ++{ ++ struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, ext_stop_scan_wq); ++#else ++void ieee80211_ext_stop_scan_wq(struct ieee80211_device *ieee) ++{ ++#endif ++/* ++ if (ieee->scanning == 0) ++ { ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_ext_stop_scan_wq_set_channel ++ && ( ieee->current_network.channel == ieee->ext_patch_ieee80211_ext_stop_scan_wq_set_channel(ieee) ) ) ++ return; ++ } ++*/ ++ ieee->sync_scan_hurryup = 1; ++ ++ down(&ieee->wx_sem); ++ ++ // printk("@@@@@@@@@@ ieee80211_ext_stop_scan_wq\n"); ++ if (ieee->data_hard_stop) ++ ieee->data_hard_stop(ieee->dev); ++ ++ ieee80211_stop_scan(ieee); ++ ++ // set channel ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_ext_stop_scan_wq_set_channel) ++ { ++ int ch = ieee->ext_patch_ieee80211_ext_stop_scan_wq_set_channel(ieee); ++ ieee->current_network.channel = ch; ++ ieee->set_chan(ieee->dev, ch); ++ } ++ else ++ { ++ ieee->set_chan(ieee->dev, ieee->current_network.channel); ++ } ++ // ++ up(&ieee->wx_sem); ++} ++ ++ ++void ieee80211_ext_send_11s_beacon(struct ieee80211_device *ieee) ++{ ++ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ queue_work(ieee->wq, &ieee->ext_send_beacon_wq); ++ #else ++ schedule_task(&ieee->ext_send_beacon_wq); ++ #endif ++ ++} ++ ++#endif // _RTL8187_EXT_PATCH_ ++ ++inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net) ++{ ++ u8 tmp_ssid[IW_ESSID_MAX_SIZE+1]; ++ int tmp_ssid_len = 0; ++ ++ short apset,ssidset,ssidbroad,apmatch,ssidmatch; ++// printk("===============>%s()\n",__FUNCTION__); ++ /* we are interested in new new only if we are not associated ++ * and we are not associating / authenticating ++ */ ++ if (ieee->state != IEEE80211_NOLINK) ++ return; ++ ++ if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS)) ++ return; ++ ++ if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS)) ++ return; ++ ++ ++ if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){ ++ /* if the user specified the AP MAC, we need also the essid ++ * This could be obtained by beacons or, if the network does not ++ * broadcast it, it can be put manually. ++ */ ++ apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 ); ++ ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0'; ++ ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0'); ++ apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0); ++ if(ieee->current_network.ssid_len != net->ssid_len) ++ ssidmatch = 0; ++ else ++ ssidmatch = (0==strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len)); ++ ++ ++ ++ if ( /* if the user set the AP check if match. ++ * if the network does not broadcast essid we check the user supplyed ANY essid ++ * if the network does broadcast and the user does not set essid it is OK ++ * if the network does broadcast and the user did set essid chech if essid match ++ */ ++ ( apset && apmatch && ++ //((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) || ++ ((ssidset && ssidbroad && ssidmatch) || (!ssidbroad && ssidset)) ) || ++ /* if the ap is not set, check that the user set the bssid ++ * and the network does bradcast and that those two bssid matches ++ */ ++ (!apset && ssidset && ssidbroad && ssidmatch) ++ ){ ++ /* if the essid is hidden replace it with the ++ * essid provided by the user. ++ */ ++ if (!ssidbroad){ ++ strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE); ++ tmp_ssid_len = ieee->current_network.ssid_len; ++ } ++ memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network)); ++ ++ if (!ssidbroad){ ++ strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE); ++ ieee->current_network.ssid_len = tmp_ssid_len; ++ } ++ printk(KERN_INFO"Linking with %s, channel:%d\n",ieee->current_network.ssid, ieee->current_network.channel); ++ ++#ifdef CONFIG_IPS ++ ieee->ieee80211_ips_leave(ieee->dev); ++#endif ++ ++ if (ieee->iw_mode == IW_MODE_INFRA){ ++ ieee->state = IEEE80211_ASSOCIATING; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ queue_work(ieee->wq, &ieee->associate_procedure_wq); ++#else ++ schedule_task(&ieee->associate_procedure_wq); ++#endif ++ }else{ ++ ieee->state = IEEE80211_LINKED; ++ if(ieee80211_is_54g(ieee->current_network) && ++ (ieee->modulation & IEEE80211_OFDM_MODULATION)){ ++ ieee->rate = 540; ++ printk(KERN_INFO"Using G rates\n"); ++ }else{ ++ ieee->rate = 110; ++ printk(KERN_INFO"Using B rates\n"); ++ } ++ } ++ ++ } ++ } ++ ++} ++ ++void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee) ++{ ++ unsigned long flags; ++ struct ieee80211_network *target; ++ ++ spin_lock_irqsave(&ieee->lock, flags); ++#if 0 ++ list_for_each_entry(target, &ieee->network_list, list) { ++ printk(KERN_INFO"check network list SSID: %s, channel: %d\n",target->ssid,target->channel); ++ } ++#endif ++ list_for_each_entry(target, &ieee->network_list, list) { ++ ++ /* if the state become different that NOLINK means ++ * we had found what we are searching for ++ */ ++ ++ if (ieee->state != IEEE80211_NOLINK) ++ break; ++ ++ if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies)) ++ ieee80211_softmac_new_net(ieee, target); ++ } ++ ++ spin_unlock_irqrestore(&ieee->lock, flags); ++ ++ //printk("<=====%s\n", __func__); ++} ++ ++ ++static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen) ++{ ++ struct ieee80211_authentication *a; ++ u8 *t; ++ if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){ ++ IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len); ++ return 0xcafe; ++ } ++ *challenge = NULL; ++ a = (struct ieee80211_authentication*) skb->data; ++ if(skb->len > (sizeof(struct ieee80211_authentication) +3)){ ++ t = skb->data + sizeof(struct ieee80211_authentication); ++ ++ if(*(t++) == MFIE_TYPE_CHALLENGE){ ++ *chlen = *(t++); ++ *challenge = (u8*)kmalloc(*chlen, GFP_ATOMIC); ++ memcpy(*challenge, t, *chlen); ++ } ++ } ++ ++ return cpu_to_le16(a->status); ++ ++} ++ ++ ++int auth_rq_parse(struct sk_buff *skb,u8* dest) ++{ ++ struct ieee80211_authentication *a; ++ ++ if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){ ++ IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len); ++ return -1; ++ } ++ a = (struct ieee80211_authentication*) skb->data; ++ ++ memcpy(dest,a->header.addr2, ETH_ALEN); ++ ++ if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN) ++ return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src) ++{ ++ u8 *tag; ++ u8 *skbend; ++ u8 *ssid=NULL; ++ u8 ssidlen = 0; ++ ++ struct ieee80211_hdr_3addr *header = ++ (struct ieee80211_hdr_3addr *) skb->data; ++ ++ if (skb->len < sizeof (struct ieee80211_hdr_3addr )) ++ return -1; /* corrupted */ ++ ++ memcpy(src,header->addr2, ETH_ALEN); ++ ++ skbend = (u8*)skb->data + skb->len; ++ ++ tag = skb->data + sizeof (struct ieee80211_hdr_3addr ); ++ ++ while (tag+1 < skbend){ ++ if (*tag == 0){ ++ ssid = tag+2; ++ ssidlen = *(tag+1); ++ break; ++ } ++ tag++; /* point to the len field */ ++ tag = tag + *(tag); /* point to the last data byte of the tag */ ++ tag++; /* point to the next tag */ ++ } ++ ++ //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src)); ++ if (ssidlen == 0) return 1; ++ ++ if (!ssid) return 1; /* ssid not found in tagged param */ ++ return (!strncmp(ssid, ieee->current_network.ssid, ssidlen)); ++ ++} ++ ++int assoc_rq_parse(struct sk_buff *skb,u8* dest) ++{ ++ struct ieee80211_assoc_request_frame *a; ++ ++ if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) - ++ sizeof(struct ieee80211_info_element))) { ++ ++ IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len); ++ return -1; ++ } ++ ++ a = (struct ieee80211_assoc_request_frame*) skb->data; ++ ++ memcpy(dest,a->header.addr2,ETH_ALEN); ++ ++ return 0; ++} ++ ++static inline u16 assoc_parse(struct sk_buff *skb, int *aid) ++{ ++ struct ieee80211_assoc_response_frame *a; ++ if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){ ++ IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len); ++ return 0xcafe; ++ } ++ ++ a = (struct ieee80211_assoc_response_frame*) skb->data; ++ *aid = le16_to_cpu(a->aid) & 0x3fff; ++ return le16_to_cpu(a->status); ++} ++ ++static inline void ++ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb) ++{ ++ u8 dest[ETH_ALEN]; ++ ++ //IEEE80211DMESG("Rx probe"); ++ ieee->softmac_stats.rx_probe_rq++; ++ //DMESG("Dest is "MACSTR, MAC2STR(dest)); ++ if (probe_rq_parse(ieee, skb, dest)){ ++ //IEEE80211DMESG("Was for me!"); ++ ieee->softmac_stats.tx_probe_rs++; ++ ieee80211_resp_to_probe(ieee, dest); ++ } ++} ++ ++//static inline void ++inline void ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb) ++{ ++ u8 dest[ETH_ALEN]; ++ int status; ++ //IEEE80211DMESG("Rx probe"); ++ ieee->softmac_stats.rx_auth_rq++; ++ ++ if ((status = auth_rq_parse(skb, dest))!= -1){ ++ ieee80211_resp_to_auth(ieee, status, dest); ++ } ++ //DMESG("Dest is "MACSTR, MAC2STR(dest)); ++ ++} ++ ++//static inline void ++inline void ++ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb) ++{ ++ ++ u8 dest[ETH_ALEN]; ++ //unsigned long flags; ++ ++ ieee->softmac_stats.rx_ass_rq++; ++ if (assoc_rq_parse(skb,dest) != -1){ ++ ieee80211_resp_to_assoc_rq(ieee, dest); ++ } ++ ++ printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest)); ++ //FIXME ++ #if 0 ++ spin_lock_irqsave(&ieee->lock,flags); ++ add_associate(ieee,dest); ++ spin_unlock_irqrestore(&ieee->lock,flags); ++ #endif ++} ++ ++ ++ ++void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr) ++{ ++ ++ struct sk_buff *buf = ieee80211_null_func(ieee, pwr); ++ ++ printk(KERN_ALERT "ieee80211_sta_ps_send_null_frame \n"); ++ if (buf) ++ softmac_ps_mgmt_xmit(buf, ieee); ++ ++} ++ ++ ++short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l) ++{ ++ int timeout = ieee->ps_timeout; ++ u8 dtim; ++ /*if(ieee->ps == IEEE80211_PS_DISABLED || ++ ieee->iw_mode != IW_MODE_INFRA || ++ ieee->state != IEEE80211_LINKED) ++ ++ return 0; ++ */ ++ dtim = ieee->current_network.dtim_data; ++ //printk("DTIM\n"); ++ if(!(dtim & IEEE80211_DTIM_VALID)) ++ return 0; ++ //printk("VALID\n"); ++ ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID; ++ ++ if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps)) ++ return 2; ++ ++ if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))) ++ return 0; ++ ++ if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))) ++ return 0; ++ ++ if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) && ++ (ieee->mgmt_queue_tail != ieee->mgmt_queue_head)) ++ return 0; ++ ++ if(time_l){ ++ *time_l = ieee->current_network.last_dtim_sta_time[0] ++ + (ieee->current_network.beacon_interval ++ * ieee->current_network.dtim_period) * 1000; ++ } ++ ++ if(time_h){ ++ *time_h = ieee->current_network.last_dtim_sta_time[1]; ++ if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0]) ++ *time_h += 1; ++ } ++ ++ return 1; ++ ++ ++} ++ ++inline void ieee80211_sta_ps(struct ieee80211_device *ieee) ++{ ++ ++ u32 th,tl; ++ short sleep; ++ ++ unsigned long flags,flags2; ++ ++ spin_lock_irqsave(&ieee->lock, flags); ++ ++ if((ieee->ps == IEEE80211_PS_DISABLED || ++ ieee->iw_mode != IW_MODE_INFRA || ++ ieee->state != IEEE80211_LINKED)){ ++ ++ // #warning CHECK_LOCK_HERE ++ spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); ++ ++ ieee80211_sta_wakeup(ieee, 1); ++ ++ spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); ++ } ++ ++ sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl); ++ /* 2 wake, 1 sleep, 0 do nothing */ ++ if(sleep == 0) ++ goto out; ++ ++ if(sleep == 1){ ++ ++ if(ieee->sta_sleep == 1) ++ ieee->enter_sleep_state(ieee->dev,th,tl); ++ ++ else if(ieee->sta_sleep == 0){ ++ // printk("send null 1\n"); ++ spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); ++ ++ if(ieee->ps_is_queue_empty(ieee->dev)){ ++ ++ ++ ieee->sta_sleep = 2; ++ ++ ieee->ps_request_tx_ack(ieee->dev); ++ ++ ieee80211_sta_ps_send_null_frame(ieee,1); ++ ++ ieee->ps_th = th; ++ ieee->ps_tl = tl; ++ } ++ spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); ++ ++ } ++ ++ ++ }else if(sleep == 2){ ++//#warning CHECK_LOCK_HERE ++ spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); ++ ++ ieee80211_sta_wakeup(ieee,1); ++ ++ spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); ++ } ++ ++out: ++ spin_unlock_irqrestore(&ieee->lock, flags); ++ ++} ++ ++void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl) ++{ ++ if(ieee->sta_sleep == 0){ ++ if(nl){ ++ printk("Warning: driver is probably failing to report TX ps error\n"); ++ ieee->ps_request_tx_ack(ieee->dev); ++ ieee80211_sta_ps_send_null_frame(ieee, 0); ++ } ++ return; ++ ++ } ++ ++ if(ieee->sta_sleep == 1) ++ ieee->sta_wake_up(ieee->dev); ++ ++ ieee->sta_sleep = 0; ++ ++ if(nl){ ++ ieee->ps_request_tx_ack(ieee->dev); ++ ieee80211_sta_ps_send_null_frame(ieee, 0); ++ } ++} ++ ++void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success) ++{ ++ unsigned long flags,flags2; ++ ++ spin_lock_irqsave(&ieee->lock, flags); ++ ++ if(ieee->sta_sleep == 2){ ++ /* Null frame with PS bit set */ ++ if(success){ ++ ieee->sta_sleep = 1; ++ ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl); ++ } ++ /* if the card report not success we can't be sure the AP ++ * has not RXed so we can't assume the AP believe us awake ++ */ ++ } ++ /* 21112005 - tx again null without PS bit if lost */ ++ else { ++ ++ if((ieee->sta_sleep == 0) && !success){ ++ spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); ++ ieee80211_sta_ps_send_null_frame(ieee, 0); ++ spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); ++ } ++ } ++ spin_unlock_irqrestore(&ieee->lock, flags); ++} ++ ++inline int ++ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, ++ struct ieee80211_rx_stats *rx_stats, u16 type, ++ u16 stype) ++{ ++ struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data; ++ u16 errcode; ++ u8* challenge=NULL; ++ int chlen=0; ++ int aid=0; ++ struct ieee80211_assoc_response_frame *assoc_resp; ++ struct ieee80211_info_element *info_element; ++ ++ if(!ieee->proto_started) ++ return 0; ++ ++ if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED && ++ ieee->iw_mode == IW_MODE_INFRA && ++ ieee->state == IEEE80211_LINKED)) ++ ++ tasklet_schedule(&ieee->ps_task); ++ ++ if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP && ++ WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON) ++ ieee->last_rx_ps_time = jiffies; ++ ++ switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { ++ case IEEE80211_STYPE_ASSOC_RESP: ++ case IEEE80211_STYPE_REASSOC_RESP: ++ ++ IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n", ++ WLAN_FC_GET_STYPE(header->frame_ctl)); ++ //printk(KERN_WARNING "Received association response\n"); ++ if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && ++ ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED && ++ ieee->iw_mode == IW_MODE_INFRA){ ++ if (0 == (errcode=assoc_parse(skb, &aid))){ ++ u16 left; ++ ++ ieee->state=IEEE80211_LINKED; ++ ieee->assoc_id = aid; ++ ieee->softmac_stats.rx_ass_ok++; ++ ++ //printk(KERN_WARNING "nic_type = %s", (rx_stats->nic_type == 1)?"rtl8187":"rtl8187B"); ++ if(1 == rx_stats->nic_type) //card type is 8187 ++ { ++ goto associate_complete; ++ } ++ assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data; ++ info_element = &assoc_resp->info_element; ++ left = skb->len - ((void*)info_element - (void*)assoc_resp); ++ ++ while (left >= sizeof(struct ieee80211_info_element_hdr)) { ++ if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) { ++ printk(KERN_WARNING "[re]associate reeponse error!"); ++ return 1; ++ } ++ switch (info_element->id) { ++ case MFIE_TYPE_GENERIC: ++ IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n", info_element->len); ++ if (info_element->len >= 8 && ++ info_element->data[0] == 0x00 && ++ info_element->data[1] == 0x50 && ++ info_element->data[2] == 0xf2 && ++ info_element->data[3] == 0x02 && ++ info_element->data[4] == 0x01) { ++ // Not care about version at present. ++ //WMM Parameter Element ++ memcpy(ieee->current_network.wmm_param,(u8*)(info_element->data\ ++ + 8),(info_element->len - 8)); ++ ++ if (((ieee->current_network.wmm_info^info_element->data[6])& \ ++ 0x0f)||(!ieee->init_wmmparam_flag)) { ++ //refresh paramete element for current network ++ // update the register parameter for hardware ++ ieee->init_wmmparam_flag = 1; ++ //ieee->wmm_param_update(ieee); ++ //schedule_work(&ieee->wmm_param_update_wq); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ queue_work(ieee->wq, &ieee->wmm_param_update_wq); ++#else ++ schedule_task(&ieee->wmm_param_update_wq); ++#endif ++ ++ } ++ //update info_element for current network ++ ieee->current_network.wmm_info = info_element->data[6]; ++ } ++ break; ++ default: ++ //nothing to do at present!!! ++ break; ++ } ++ ++ left -= sizeof(struct ieee80211_info_element_hdr) + ++ info_element->len; ++ info_element = (struct ieee80211_info_element *) ++ &info_element->data[info_element->len]; ++ } ++ if(!ieee->init_wmmparam_flag) //legacy AP, reset the AC_xx_param register ++ { ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ queue_work(ieee->wq,&ieee->wmm_param_update_wq); ++#else ++ schedule_task(&ieee->wmm_param_update_wq); ++#endif ++ ieee->init_wmmparam_flag = 1;//indicate AC_xx_param upated since last associate ++ } ++associate_complete: ++ ieee80211_associate_complete(ieee); ++ }else{ ++ ieee->softmac_stats.rx_ass_err++; ++ IEEE80211_DEBUG_MGMT( ++ "Association response status code 0x%x\n", ++ errcode); ++ printk(KERN_WARNING "Association response status code 0x%x\n", ++ errcode); ++ ieee80211_associate_abort(ieee); ++ } ++ } ++#ifdef _RTL8187_EXT_PATCH_ ++ else if ((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_rx_frame_softmac_on_assoc_rsp) ++ { ++ ieee->ext_patch_ieee80211_rx_frame_softmac_on_assoc_rsp(ieee, skb); ++ } ++#endif ++ break; ++ ++ case IEEE80211_STYPE_ASSOC_REQ: ++ case IEEE80211_STYPE_REASSOC_REQ: ++ //printk("Received IEEE80211_STYPE_ASSOC_REQ\n"); ++ ++ if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && ++ ieee->iw_mode == IW_MODE_MASTER) ++ ++ ieee80211_rx_assoc_rq(ieee, skb); ++#ifdef _RTL8187_EXT_PATCH_ ++ else if ((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_rx_frame_softmac_on_assoc_req) ++ { ++ ieee->ext_patch_ieee80211_rx_frame_softmac_on_assoc_req(ieee, skb); ++ } ++#endif ++ break; ++ ++ case IEEE80211_STYPE_AUTH: ++ //printk("Received authentication response\n"); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++//printk("IEEE80211_STYPE_AUTH\n"); ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_rx_frame_softmac_on_auth) ++ if( ieee->ext_patch_ieee80211_rx_frame_softmac_on_auth(ieee, skb, rx_stats) ); ++#endif ++ if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){ ++ if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING && ++ ieee->iw_mode == IW_MODE_INFRA){ ++ ++ IEEE80211_DEBUG_MGMT("Received authentication response"); ++ ++ if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){ ++ if(ieee->open_wep || !challenge){ ++ ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED; ++ ieee->softmac_stats.rx_auth_rs_ok++; ++ ++ ieee80211_associate_step2(ieee); ++ }else{ ++ ieee80211_auth_challenge(ieee, challenge, chlen); ++ } ++ }else{ ++ ieee->softmac_stats.rx_auth_rs_err++; ++ IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode); ++ ieee80211_associate_abort(ieee); ++ } ++ ++ }else if (ieee->iw_mode == IW_MODE_MASTER){ ++ ieee80211_rx_auth_rq(ieee, skb); ++ } ++ } ++ break; ++ ++ case IEEE80211_STYPE_PROBE_REQ: ++ //printk("Received IEEE80211_STYPE_PROBE_REQ\n"); ++ ++ if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) && ++ ((ieee->iw_mode == IW_MODE_ADHOC || ++ ieee->iw_mode == IW_MODE_MASTER) && ++ ieee->state == IEEE80211_LINKED)) ++ ++ ieee80211_rx_probe_rq(ieee, skb); ++ break; ++ ++ case IEEE80211_STYPE_DISASSOC: ++ case IEEE80211_STYPE_DEAUTH: ++ //printk("Received IEEE80211_STYPE_DISASSOC\n"); ++#ifdef _RTL8187_EXT_PATCH_ ++//printk("IEEE80211_STYPE_DEAUTH\n"); ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_rx_frame_softmac_on_deauth) ++ if( ieee->ext_patch_ieee80211_rx_frame_softmac_on_deauth(ieee, skb, rx_stats) ) ; ++#endif ++ /* FIXME for now repeat all the association procedure ++ * both for disassociation and deauthentication ++ */ ++ if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && ++ ieee->state == IEEE80211_LINKED && ++ ieee->iw_mode == IW_MODE_INFRA){ ++ ++ ieee->state = IEEE80211_ASSOCIATING; ++ ieee->softmac_stats.reassoc++; ++ ++ notify_wx_assoc_event(ieee); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ queue_work(ieee->wq, &ieee->associate_procedure_wq); ++#else ++ schedule_task(&ieee->associate_procedure_wq); ++#endif ++ } ++ ++ break; ++ ++ default: ++ return -1; ++ break; ++ } ++ ++ //dev_kfree_skb_any(skb); ++ return 0; ++} ++ ++ ++ ++/* following are for a simplier TX queue management. ++ * Instead of using netif_[stop/wake]_queue the driver ++ * will uses these two function (plus a reset one), that ++ * will internally uses the kernel netif_* and takes ++ * care of the ieee802.11 fragmentation. ++ * So the driver receives a fragment per time and might ++ * call the stop function when it want without take care ++ * to have enought room to TX an entire packet. ++ * This might be useful if each fragment need it's own ++ * descriptor, thus just keep a total free memory > than ++ * the max fragmentation treshold is not enought.. If the ++ * ieee802.11 stack passed a TXB struct then you needed ++ * to keep N free descriptors where ++ * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD ++ * In this way you need just one and the 802.11 stack ++ * will take care of buffering fragments and pass them to ++ * to the driver later, when it wakes the queue. ++ */ ++ ++void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee) ++{ ++ ++ ++ unsigned long flags; ++ int i; ++#ifdef _RTL8187_EXT_PATCH_ ++ int rate = ieee->rate; ++#endif ++ ++ spin_lock_irqsave(&ieee->lock,flags); ++ #if 0 ++ if(ieee->queue_stop){ ++ IEEE80211DMESG("EE: IEEE hard_start_xmit invoked when kernel queue should be stopped"); ++ netif_stop_queue(ieee->dev); ++ ieee->ieee_stats.swtxstop++; ++ //dev_kfree_skb_any(skb); ++ err = 1; ++ goto exit; ++ } ++ ++ ieee->stats.tx_bytes+=skb->len; ++ ++ ++ txb=ieee80211_skb_to_txb(ieee,skb); ++ ++ ++ if(txb==NULL){ ++ IEEE80211DMESG("WW: IEEE stack failed to provide txb"); ++ //dev_kfree_skb_any(skb); ++ err = 1; ++ goto exit; ++ } ++ #endif ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_softmac_xmit_get_rate && txb->nr_frags) ++ { ++ rate = ieee->ext_patch_ieee80211_softmac_xmit_get_rate(ieee, txb->fragments[0]); ++ } ++#endif ++ /* called with 2nd parm 0, no tx mgmt lock required */ ++ ieee80211_sta_wakeup(ieee,0); ++ ++ for(i = 0; i < txb->nr_frags; i++) { ++ ++ if (ieee->queue_stop){ ++ ieee->tx_pending.txb = txb; ++ ieee->tx_pending.frag = i; ++ goto exit; ++ }else{ ++ ieee->softmac_data_hard_start_xmit( ++ txb->fragments[i], ++#ifdef _RTL8187_EXT_PATCH_ ++ ieee->dev, rate); ++#else ++ ieee->dev,ieee->rate); ++#endif ++ //(i+1)nr_frags); ++ ieee->stats.tx_packets++; ++ ieee->stats.tx_bytes += txb->fragments[i]->len; ++ ieee->dev->trans_start = jiffies; ++ } ++ } ++ ++ ieee80211_txb_free(txb); ++ ++ exit: ++ spin_unlock_irqrestore(&ieee->lock,flags); ++ ++} ++ ++/* called with ieee->lock acquired */ ++void ieee80211_resume_tx(struct ieee80211_device *ieee) ++{ ++ int i; ++ for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) { ++ ++ if (ieee->queue_stop){ ++ ieee->tx_pending.frag = i; ++ return; ++ }else{ ++ ++ ieee->softmac_data_hard_start_xmit( ++ ieee->tx_pending.txb->fragments[i], ++ ieee->dev,ieee->rate); ++ //(i+1)tx_pending.txb->nr_frags); ++ ieee->stats.tx_packets++; ++ ieee->dev->trans_start = jiffies; ++ } ++ } ++ ++ ++ ieee80211_txb_free(ieee->tx_pending.txb); ++ ieee->tx_pending.txb = NULL; ++} ++ ++ ++void ieee80211_reset_queue(struct ieee80211_device *ieee) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ieee->lock,flags); ++ init_mgmt_queue(ieee); ++ if (ieee->tx_pending.txb){ ++ ieee80211_txb_free(ieee->tx_pending.txb); ++ ieee->tx_pending.txb = NULL; ++ } ++ ieee->queue_stop = 0; ++ spin_unlock_irqrestore(&ieee->lock,flags); ++ ++} ++ ++void ieee80211_wake_queue(struct ieee80211_device *ieee) ++{ ++ ++ unsigned long flags; ++ struct sk_buff *skb; ++ struct ieee80211_hdr_3addr *header; ++ ++ spin_lock_irqsave(&ieee->lock,flags); ++ if (! ieee->queue_stop) goto exit; ++ ++ ieee->queue_stop = 0; ++ ++ if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){ ++ while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){ ++ ++ header = (struct ieee80211_hdr_3addr *) skb->data; ++ ++ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); ++ ++ if (ieee->seq_ctrl[0] == 0xFFF) ++ ieee->seq_ctrl[0] = 0; ++ else ++ ieee->seq_ctrl[0]++; ++ ++ printk(KERN_ALERT "ieee80211_wake_queue \n"); ++ ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); ++ dev_kfree_skb_any(skb);//edit by thomas ++ } ++ } ++ if (!ieee->queue_stop && ieee->tx_pending.txb) ++ ieee80211_resume_tx(ieee); ++ ++ if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){ ++ ieee->softmac_stats.swtxawake++; ++ netif_wake_queue(ieee->dev); ++ } ++ ++exit : ++ spin_unlock_irqrestore(&ieee->lock,flags); ++} ++ ++ ++void ieee80211_stop_queue(struct ieee80211_device *ieee) ++{ ++ //unsigned long flags; ++ //spin_lock_irqsave(&ieee->lock,flags); ++ ++ if (! netif_queue_stopped(ieee->dev)){ ++ netif_stop_queue(ieee->dev); ++ ieee->softmac_stats.swtxstop++; ++ } ++ ieee->queue_stop = 1; ++ //spin_unlock_irqrestore(&ieee->lock,flags); ++ ++} ++ ++ ++inline void ieee80211_randomize_cell(struct ieee80211_device *ieee) ++{ ++ ++ get_random_bytes(ieee->current_network.bssid, ETH_ALEN); ++ ++ /* an IBSS cell address must have the two less significant ++ * bits of the first byte = 2 ++ */ ++ ieee->current_network.bssid[0] &= ~0x01; ++ ieee->current_network.bssid[0] |= 0x02; ++} ++ ++/* called in user context only */ ++void ieee80211_start_master_bss(struct ieee80211_device *ieee) ++{ ++ ieee->assoc_id = 1; ++ ++ if (ieee->current_network.ssid_len == 0){ ++ strncpy(ieee->current_network.ssid, ++ IEEE80211_DEFAULT_TX_ESSID, ++ IW_ESSID_MAX_SIZE); ++ ++ ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID); ++ ieee->ssid_set = 1; ++ } ++ ++ memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN); ++ ++ ieee->set_chan(ieee->dev, ieee->current_network.channel); ++ ieee->state = IEEE80211_LINKED; ++ ++//by lizhaoming for LED LINK ++#ifdef LED_SHIN ++ { ++ struct net_device *dev = ieee->dev; ++ ieee->ieee80211_led_contorl(dev, LED_CTL_LINK); ++ } ++#endif ++ ieee->link_change(ieee->dev); ++ notify_wx_assoc_event(ieee); ++ ++ if (ieee->data_hard_resume) ++ ieee->data_hard_resume(ieee->dev); ++ ++ netif_carrier_on(ieee->dev); ++} ++ ++void ieee80211_start_monitor_mode(struct ieee80211_device *ieee) ++{ ++ if(ieee->raw_tx){ ++ ++ if (ieee->data_hard_resume) ++ ieee->data_hard_resume(ieee->dev); ++ ++ netif_carrier_on(ieee->dev); ++ } ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void ieee80211_start_ibss_wq(struct work_struct *work) ++{ ++ struct delayed_work *dwork = container_of(work, struct delayed_work, work); ++ struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq); ++#else ++void ieee80211_start_ibss_wq(struct ieee80211_device *ieee) ++{ ++#endif ++ ++ /* iwconfig mode ad-hoc will schedule this and return ++ * on the other hand this will block further iwconfig SET ++ * operations because of the wx_sem hold. ++ * Anyway some most set operations set a flag to speed-up ++ * (abort) this wq (when syncro scanning) before sleeping ++ * on the semaphore ++ */ ++ ++ down(&ieee->wx_sem); ++ ++ if (ieee->current_network.ssid_len == 0){ ++ strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID); ++ ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID); ++ ieee->ssid_set = 1; ++ } ++ ++//by lizhaoming for LED BLINK 2008.6.23 ++#ifdef LED_SHIN ++ { ++ struct net_device *dev = ieee->dev; ++ ieee->ieee80211_led_contorl(dev, LED_CTL_SITE_SURVEY); ++ } ++#endif ++ ++ /* check if we have this cell in our network list */ ++ ieee80211_softmac_check_all_nets(ieee); ++ ++#ifdef ENABLE_DOT11D ++ //[World wide 13]: ++ // Adhoc: ++ // (1) active scan from ch1~11 and passive scan from ch12~13 ++ // (2) IBSS can join ch1~13 adhoc, but only start at ch10. ++ if(ieee->state == IEEE80211_NOLINK) ++ if(ieee->IbssStartChnl != 0) ++ ieee->current_network.channel = ieee->IbssStartChnl;//chan 10 ++#endif ++ ++ /* if not then the state is not linked. Maybe the user swithced to ++ * ad-hoc mode just after being in monitor mode, or just after ++ * being very few time in managed mode (so the card have had no ++ * time to scan all the chans..) or we have just run up the iface ++ * after setting ad-hoc mode. So we have to give another try.. ++ * Here, in ibss mode, should be safe to do this without extra care ++ * (in bss mode we had to make sure no-one tryed to associate when ++ * we had just checked the ieee->state and we was going to start the ++ * scan) beacause in ibss mode the ieee80211_new_net function, when ++ * finds a good net, just set the ieee->state to IEEE80211_LINKED, ++ * so, at worst, we waste a bit of time to initiate an unneeded syncro ++ * scan, that will stop at the first round because it sees the state ++ * associated. ++ */ ++ if (ieee->state == IEEE80211_NOLINK){ ++ ieee80211_start_scan_syncro(ieee); ++ } ++ ++ /* the network definitively is not here.. create a new cell */ ++ if (ieee->state == IEEE80211_NOLINK){ ++ printk("creating new IBSS cell\n"); ++ ieee->state = IEEE80211_LINKED; ++ if(!ieee->wap_set) ++ ieee80211_randomize_cell(ieee); ++ ++ if(ieee->modulation & IEEE80211_CCK_MODULATION){ ++ ++ ieee->current_network.rates_len = 4; ++ ++ ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; ++ ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; ++ ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; ++ ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; ++ ++ }else ++ ieee->current_network.rates_len = 0; ++ ++ if(ieee->modulation & IEEE80211_OFDM_MODULATION){ ++ ieee->current_network.rates_ex_len = 8; ++ ++ ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; ++ ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; ++ ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; ++ ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; ++ ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; ++ ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; ++ ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; ++ ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; ++ ++ ieee->rate = 540; ++ }else{ ++ ieee->current_network.rates_ex_len = 0; ++ ieee->rate = 110; ++ } ++ ++ // By default, WMM function will be disabled in IBSS mode ++ ieee->current_network.QoS_Enable = 0; ++ ++ ieee->current_network.atim_window = 0; ++ ieee->current_network.capability = WLAN_CAPABILITY_IBSS; ++ if(ieee->short_slot) ++ ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT; ++ ++ } ++ ++ ieee->state = IEEE80211_LINKED; ++ ++//by lizhaoming for LED LINK ++#ifdef LED_SHIN ++ { ++ struct net_device *dev = ieee->dev; ++ ieee->ieee80211_led_contorl(dev, LED_CTL_LINK); ++ } ++#endif ++ ++ ieee->set_chan(ieee->dev, ieee->current_network.channel); ++ ieee->link_change(ieee->dev); ++ ++ notify_wx_assoc_event(ieee); ++ ++ ieee80211_start_send_beacons(ieee); ++ printk(KERN_WARNING "after sending beacon packet!\n"); ++ ++ if (ieee->data_hard_resume) ++ ieee->data_hard_resume(ieee->dev); ++ ++ netif_carrier_on(ieee->dev); ++ ++ up(&ieee->wx_sem); ++} ++ ++inline void ieee80211_start_ibss(struct ieee80211_device *ieee) ++{ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150); //change to delayed work, delayed time is need to check ++#else ++ schedule_task(&ieee->start_ibss_wq); ++#endif ++} ++ ++/* this is called only in user context, with wx_sem held */ ++void ieee80211_start_bss(struct ieee80211_device *ieee) ++{ ++ unsigned long flags; ++ /* check if we have already found the net we ++ * are interested in (if any). ++ * if not (we are disassociated and we are not ++ * in associating / authenticating phase) start the background scanning. ++ */ ++ ++//by lizhaoming for LED BLINK 2008.6.23 ++#ifdef LED_SHIN ++ { ++ struct net_device *dev = ieee->dev; ++ ieee->ieee80211_led_contorl(dev, LED_CTL_SITE_SURVEY); ++ } ++#endif ++ ++#ifdef ENABLE_DOT11D ++ // ++ // Ref: 802.11d 11.1.3.3 ++ // STA shall not start a BSS unless properly formed Beacon frame including a Country IE. ++ // ++ if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) ++ { ++ if(! ieee->bGlobalDomain) ++ { ++ return; ++ } ++ } ++#endif ++ //printk("======>%s()\n",__FUNCTION__); ++ ieee80211_softmac_check_all_nets(ieee); ++ ++ /* ensure no-one start an associating process (thus setting ++ * the ieee->state to ieee80211_ASSOCIATING) while we ++ * have just cheked it and we are going to enable scan. ++ * The ieee80211_new_net function is always called with ++ * lock held (from both ieee80211_softmac_check_all_nets and ++ * the rx path), so we cannot be in the middle of such function ++ */ ++ ++ spin_lock_irqsave(&ieee->lock, flags); ++ if (ieee->state == IEEE80211_NOLINK){ ++ //printk("Not find SSID in network list scan now\n"); ++ ieee80211_start_scan(ieee); ++ } ++ spin_unlock_irqrestore(&ieee->lock, flags); ++ ++} ++ ++/* called only in userspace context */ ++void ieee80211_disassociate(struct ieee80211_device *ieee) ++{ ++ netif_carrier_off(ieee->dev); ++ ++ if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) ++ ieee80211_reset_queue(ieee); ++ ++ if (ieee->data_hard_stop) ++ ieee->data_hard_stop(ieee->dev); ++ ++#ifdef ENABLE_DOT11D ++ if(IS_DOT11D_ENABLE(ieee)) ++ Dot11d_Reset(ieee); ++#endif ++ ++ ieee->state = IEEE80211_NOLINK; ++ ieee->link_change(ieee->dev); ++ notify_wx_assoc_event(ieee); ++ ++} ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void ieee80211_associate_retry_wq(struct work_struct *work) ++{ ++ struct delayed_work *dwork = container_of(work, struct delayed_work, work); ++ struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq); ++#else ++void ieee80211_associate_retry_wq(struct ieee80211_device *ieee) ++{ ++#endif ++ unsigned long flags; ++ ++ down(&ieee->wx_sem); ++ if(!ieee->proto_started) ++ goto exit; ++ ++ if(ieee->state != IEEE80211_ASSOCIATING_RETRY) ++ goto exit; ++ ++ /* until we do not set the state to IEEE80211_NOLINK ++ * there are no possibility to have someone else trying ++ * to start an association procdure (we get here with ++ * ieee->state = IEEE80211_ASSOCIATING). ++ * When we set the state to IEEE80211_NOLINK it is possible ++ * that the RX path run an attempt to associate, but ++ * both ieee80211_softmac_check_all_nets and the ++ * RX path works with ieee->lock held so there are no ++ * problems. If we are still disassociated then start a scan. ++ * the lock here is necessary to ensure no one try to start ++ * an association procedure when we have just checked the ++ * state and we are going to start the scan. ++ */ ++ ieee->state = IEEE80211_NOLINK; ++ ++ ieee80211_softmac_check_all_nets(ieee); ++ ++ spin_lock_irqsave(&ieee->lock, flags); ++ if(ieee->state == IEEE80211_NOLINK) ++ { ++ printk("%s():Not find SSID:%s[ch=%d, mode=%s] in network list scan now\n", __FUNCTION__, ++ ieee->current_network.ssid,ieee->current_network.channel, ++ (ieee->iw_mode == IW_MODE_INFRA) ? "BSS" : "IBSS"); ++ ++ ieee80211_start_scan(ieee); ++ } ++ ++ spin_unlock_irqrestore(&ieee->lock, flags); ++ ++exit: ++ up(&ieee->wx_sem); ++} ++ ++struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee) ++{ ++ u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff}; ++ ++ struct sk_buff *skb = NULL; ++ struct ieee80211_probe_response *b; ++ ++//rz ++#ifdef _RTL8187_EXT_PATCH_ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_get_beacon_get_probersp ) ++ skb = ieee->ext_patch_get_beacon_get_probersp(ieee, broadcast_addr, &(ieee->current_network)); ++ else ++ skb = ieee80211_probe_resp(ieee, broadcast_addr); ++#else ++ skb = ieee80211_probe_resp(ieee, broadcast_addr); ++#endif ++// ++ if (!skb) ++ return NULL; ++ ++ b = (struct ieee80211_probe_response *) skb->data; ++ b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON); ++ ++ return skb; ++ ++} ++ ++struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee) ++{ ++ struct sk_buff *skb; ++ struct ieee80211_probe_response *b; ++// printk("=========>%s()\n", __FUNCTION__); ++ skb = ieee80211_get_beacon_(ieee); ++ if(!skb) ++ return NULL; ++ ++ b = (struct ieee80211_probe_response *) skb->data; ++ b->header.seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); ++ ++ if (ieee->seq_ctrl[0] == 0xFFF) ++ ieee->seq_ctrl[0] = 0; ++ else ++ ieee->seq_ctrl[0]++; ++ ++ return skb; ++} ++ ++void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee) ++{ ++ ieee->sync_scan_hurryup = 1; ++ down(&ieee->wx_sem); ++ ieee80211_stop_protocol(ieee); ++ up(&ieee->wx_sem); ++} ++ ++ ++void ieee80211_stop_protocol(struct ieee80211_device *ieee) ++{ ++ if (!ieee->proto_started) ++ return; ++ ++ ieee->proto_started = 0; ++ //printk("=====>%s\n", __func__); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(ieee->ext_patch_ieee80211_stop_protocol) ++ ieee->ext_patch_ieee80211_stop_protocol(ieee); ++//if call queue_delayed_work,can call this,or do nothing.. ++//edit by lawrence,20071118 ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++// cancel_delayed_work(&ieee->ext_stop_scan_wq); ++// cancel_delayed_work(&ieee->ext_send_beacon_wq); ++#endif ++#endif // _RTL8187_EXT_PATCH_ ++ ++ ieee80211_stop_send_beacons(ieee); ++ ++ del_timer_sync(&ieee->associate_timer); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ cancel_delayed_work(&ieee->associate_retry_wq); ++ cancel_delayed_work(&ieee->start_ibss_wq); //cancel ibss start workqueue when stop protocol ++#endif ++ ieee80211_stop_scan(ieee); ++ ++ ieee80211_disassociate(ieee); ++ //printk("<=====%s\n", __func__); ++ ++} ++ ++void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee) ++{ ++ ieee->sync_scan_hurryup = 0; ++ down(&ieee->wx_sem); ++ ieee80211_start_protocol(ieee); ++ up(&ieee->wx_sem); ++} ++ ++void ieee80211_start_protocol(struct ieee80211_device *ieee) ++{ ++ short ch = 0; ++ int i = 0; ++ ++ if (ieee->proto_started) ++ return; ++ ++ //printk("=====>%s\n", __func__); ++ ++ ieee->proto_started = 1; ++ ++ if (ieee->current_network.channel == 0){ ++ do{ ++ ch++; ++ if (ch > MAX_CHANNEL_NUMBER) ++ return; /* no channel found */ ++#ifdef ENABLE_DOT11D ++ }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]); ++#else ++ }while(!ieee->channel_map[ch]); ++#endif ++ ieee->current_network.channel = ch; ++ } ++ ++ if (ieee->current_network.beacon_interval == 0) ++ ieee->current_network.beacon_interval = 100; ++ ++ ieee->set_chan(ieee->dev,ieee->current_network.channel); ++ mdelay(10);//must or link change will fail lzm ++ ++ for(i = 0; i < 17; i++) { ++ ieee->last_rxseq_num[i] = -1; ++ ieee->last_rxfrag_num[i] = -1; ++ ieee->last_packet_time[i] = 0; ++ } ++ ++ ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers. ++ ++ ++ /* if the user set the MAC of the ad-hoc cell and then ++ * switch to managed mode, shall we make sure that association ++ * attempts does not fail just because the user provide the essid ++ * and the nic is still checking for the AP MAC ?? ++ */ ++ ++ if (ieee->iw_mode == IW_MODE_INFRA){ ++ ieee80211_start_bss(ieee); ++ // printk("==========> IW_MODE_INFRA\n"); ++ } ++ else if (ieee->iw_mode == IW_MODE_ADHOC){ ++ // printk("==========> IW_MODE_ADHOC\n"); ++ ieee80211_start_ibss(ieee); ++ } ++ else if (ieee->iw_mode == IW_MODE_MASTER){ ++ ieee80211_start_master_bss(ieee); ++// printk("==========> IW_MODE_MASTER\n"); ++ } ++ else if(ieee->iw_mode == IW_MODE_MONITOR){ ++ ieee80211_start_monitor_mode(ieee); ++// printk("==========> IW_MODE_MONITOR\n"); ++ } ++ ++#ifdef _RTL8187_EXT_PATCH_ ++// else if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_start_protocol && ieee->ext_patch_ieee80211_start_protocol(ieee)) ++ else if((ieee->iw_mode == ieee->iw_ext_mode) && ieee->ext_patch_ieee80211_start_protocol) ++ { ++ ieee->ext_patch_ieee80211_start_mesh(ieee); ++ } ++#endif ++} ++ ++ ++#define DRV_NAME "Ieee80211" ++void ieee80211_softmac_init(struct ieee80211_device *ieee) ++{ ++ int i; ++ memset(&ieee->current_network, 0, sizeof(struct ieee80211_network)); ++ ++ ieee->state = IEEE80211_NOLINK; ++ ieee->sync_scan_hurryup = 0; ++ for(i = 0; i < 5; i++) { ++ ieee->seq_ctrl[i] = 0; ++ } ++ ++ ieee->assoc_id = 0; ++ ieee->queue_stop = 0; ++ ieee->scanning = 0; ++ ieee->scan_watchdog = 0;//lzm add 081215 for roaming ++ ieee->softmac_features = 0; //so IEEE2100-like driver are happy ++ ieee->wap_set = 0; ++ ieee->ssid_set = 0; ++ ieee->proto_started = 0; ++ ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE; ++ ieee->rate = 3; ++ ieee->ps = IEEE80211_PS_DISABLED; ++ ieee->sta_sleep = 0; ++//by amy ++ ieee->bInactivePs = false; ++ ieee->actscanning = false; ++ ieee->ListenInterval = 2; ++ ieee->NumRxData = 0; ++ ieee->NumRxDataInPeriod = 0; //YJ,add,080828 ++ ieee->NumRxBcnInPeriod = 0; //YJ,add,080828 ++ ieee->bHwRadioOff = false;//by lizhaoming ++//by amy ++#ifdef _RTL8187_EXT_PATCH_ ++ ieee->iw_ext_mode = 999; ++#endif ++ ++ init_mgmt_queue(ieee); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ++ init_timer(&ieee->scan_timer); ++ ieee->scan_timer.data = (unsigned long)ieee; ++ ieee->scan_timer.function = ieee80211_softmac_scan_cb; ++#endif ++ ieee->tx_pending.txb = NULL; ++ ++ init_timer(&ieee->associate_timer); ++ ieee->associate_timer.data = (unsigned long)ieee; ++ ieee->associate_timer.function = ieee80211_associate_abort_cb; ++ ++ init_timer(&ieee->beacon_timer); ++ ieee->beacon_timer.data = (unsigned long) ieee; ++ ieee->beacon_timer.function = ieee80211_send_beacon_cb; ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++#ifdef PF_SYNCTHREAD ++ ieee->wq = create_workqueue(DRV_NAME,0); ++#else ++ ieee->wq = create_workqueue(DRV_NAME); ++#endif ++#endif ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)//added by lawrence,070702 ++ INIT_DELAYED_WORK(&ieee->start_ibss_wq, ieee80211_start_ibss_wq); ++ INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq); ++ INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq); ++ INIT_DELAYED_WORK(&ieee->softmac_scan_wq, ieee80211_softmac_scan_wq); ++ INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq); ++ INIT_WORK(&ieee->wx_sync_scan_wq, ieee80211_wx_sync_scan_wq); ++//added by lawrence,20071118 ++#ifdef _RTL8187_EXT_PATCH_ ++ INIT_WORK(&ieee->ext_stop_scan_wq, ieee80211_ext_stop_scan_wq); ++ //INIT_WORK(&ieee->ext_send_beacon_wq, ieee80211_beacons_start,ieee); ++ INIT_WORK(&ieee->ext_send_beacon_wq, ext_ieee80211_send_beacon_wq); ++#endif //_RTL8187_EXT_PATCH_ ++#else ++ INIT_WORK(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee); ++ INIT_WORK(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee); ++ INIT_WORK(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee); ++ INIT_WORK(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee); ++ INIT_WORK(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee); ++ INIT_WORK(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee); ++#ifdef _RTL8187_EXT_PATCH_ ++ INIT_WORK(&ieee->ext_stop_scan_wq,(void(*)(void*)) ieee80211_ext_stop_scan_wq,ieee); ++ //INIT_WORK(&ieee->ext_send_beacon_wq,(void(*)(void*)) ieee80211_beacons_start,ieee); ++ INIT_WORK(&ieee->ext_send_beacon_wq,(void(*)(void*)) ext_ieee80211_send_beacon_wq,ieee); ++#endif ++#endif ++#else ++ tq_init(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee); ++ tq_init(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee); ++ tq_init(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee); ++ tq_init(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee); ++ tq_init(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee); ++ tq_init(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee); ++#ifdef _RTL8187_EXT_PATCH_ ++ tq_init(&ieee->ext_stop_scan_wq,(void(*)(void*)) ieee80211_ext_stop_scan_wq,ieee); ++ //tq_init(&ieee->ext_send_beacon_wq,(void(*)(void*)) ieee80211_beacons_start,ieee); ++ tq_init(&ieee->ext_send_beacon_wq,(void(*)(void*)) ext_ieee80211_send_beacon_wq,ieee); ++#endif ++#endif ++ sema_init(&ieee->wx_sem, 1); ++ sema_init(&ieee->scan_sem, 1); ++ sema_init(&ieee->ips_sem,1); ++ spin_lock_init(&ieee->mgmt_tx_lock); ++ spin_lock_init(&ieee->beacon_lock); ++ spin_lock_init(&ieee->beaconflag_lock); ++ tasklet_init(&ieee->ps_task, ++ (void(*)(unsigned long)) ieee80211_sta_ps, ++ (unsigned long)ieee); ++#ifdef ENABLE_DOT11D ++ ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC); ++#endif ++ ++} ++ ++void ieee80211_softmac_free(struct ieee80211_device *ieee) ++{ ++ down(&ieee->wx_sem); ++ ++ del_timer_sync(&ieee->associate_timer); ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ cancel_delayed_work(&ieee->associate_retry_wq); ++ ++ ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ //When kernel>2.6.20,crash.... ++// cancel_delayed_work(&ieee->ext_stop_scan_wq); ++// cancel_delayed_work(&ieee->ext_send_beacon_wq); ++#endif ++ destroy_workqueue(ieee->wq); ++#endif ++ ++#ifdef ENABLE_DOT11D ++ if(NULL != ieee->pDot11dInfo) ++ kfree(ieee->pDot11dInfo); ++#endif ++ ++ up(&ieee->wx_sem); ++} ++ ++/******************************************************** ++ * Start of WPA code. * ++ * this is stolen from the ipw2200 driver * ++ ********************************************************/ ++ ++ ++static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value) ++{ ++ /* This is called when wpa_supplicant loads and closes the driver ++ * interface. */ ++ printk("%s WPA\n",value ? "enabling" : "disabling"); ++ ieee->wpa_enabled = value; ++ return 0; ++} ++ ++ ++void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len) ++{ ++ /* make sure WPA is enabled */ ++ ieee80211_wpa_enable(ieee, 1); ++ ++ ieee80211_disassociate(ieee); ++} ++ ++ ++static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason) ++{ ++ ++ int ret = 0; ++ ++ switch (command) { ++ case IEEE_MLME_STA_DEAUTH: ++ // silently ignore ++ break; ++ ++ case IEEE_MLME_STA_DISASSOC: ++ ieee80211_disassociate(ieee); ++ break; ++ ++ default: ++ printk("Unknown MLME request: %d\n", command); ++ ret = -EOPNOTSUPP; ++ } ++ ++ return ret; ++} ++ ++ ++static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee, ++ struct ieee_param *param, int plen) ++{ ++ u8 *buf; ++ ++ if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || ++ (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) ++ return -EINVAL; ++ ++ if (param->u.wpa_ie.len) { ++ buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL); ++ if (buf == NULL) ++ return -ENOMEM; ++ ++ memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len); ++ kfree(ieee->wpa_ie); ++ ieee->wpa_ie = buf; ++ ieee->wpa_ie_len = param->u.wpa_ie.len; ++ } else { ++ kfree(ieee->wpa_ie); ++ ieee->wpa_ie = NULL; ++ ieee->wpa_ie_len = 0; ++ } ++ ++ ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len); ++ return 0; ++} ++ ++#define AUTH_ALG_OPEN_SYSTEM 0x1 ++#define AUTH_ALG_SHARED_KEY 0x2 ++ ++static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value) ++{ ++ ++ struct ieee80211_security sec = { ++ .flags = SEC_AUTH_MODE, ++ }; ++ int ret = 0; ++ ++ if (value & AUTH_ALG_SHARED_KEY) { ++ sec.auth_mode = WLAN_AUTH_SHARED_KEY; ++ ieee->open_wep = 0; ++ } else { ++ sec.auth_mode = WLAN_AUTH_OPEN; ++ ieee->open_wep = 1; ++ } ++ ++ if (ieee->set_security) ++ ieee->set_security(ieee->dev, &sec); ++ else ++ ret = -EOPNOTSUPP; ++ ++ return ret; ++} ++ ++static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value) ++{ ++ int ret=0; ++ unsigned long flags; ++ ++ switch (name) { ++ case IEEE_PARAM_WPA_ENABLED: ++ ret = ieee80211_wpa_enable(ieee, value); ++ break; ++ ++ case IEEE_PARAM_TKIP_COUNTERMEASURES: ++ ieee->tkip_countermeasures=value; ++ break; ++ ++ case IEEE_PARAM_DROP_UNENCRYPTED: { ++ /* HACK: ++ * ++ * wpa_supplicant calls set_wpa_enabled when the driver ++ * is loaded and unloaded, regardless of if WPA is being ++ * used. No other calls are made which can be used to ++ * determine if encryption will be used or not prior to ++ * association being expected. If encryption is not being ++ * used, drop_unencrypted is set to false, else true -- we ++ * can use this to determine if the CAP_PRIVACY_ON bit should ++ * be set. ++ */ ++ struct ieee80211_security sec = { ++ .flags = SEC_ENABLED, ++ .enabled = value, ++ }; ++ ieee->drop_unencrypted = value; ++ /* We only change SEC_LEVEL for open mode. Others ++ * are set by ipw_wpa_set_encryption. ++ */ ++ if (!value) { ++ sec.flags |= SEC_LEVEL; ++ sec.level = SEC_LEVEL_0; ++ } ++ else { ++ sec.flags |= SEC_LEVEL; ++ sec.level = SEC_LEVEL_1; ++ } ++ if (ieee->set_security) ++ ieee->set_security(ieee->dev, &sec); ++ break; ++ } ++ ++ case IEEE_PARAM_PRIVACY_INVOKED: ++ ieee->privacy_invoked=value; ++ break; ++ ++ case IEEE_PARAM_AUTH_ALGS: ++ ret = ieee80211_wpa_set_auth_algs(ieee, value); ++ break; ++ ++ case IEEE_PARAM_IEEE_802_1X: ++ ieee->ieee802_1x=value; ++ break; ++ case IEEE_PARAM_WPAX_SELECT: ++ // added for WPA2 mixed mode ++ //printk(KERN_WARNING "------------------------>wpax value = %x\n", value); ++ spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags); ++ ieee->wpax_type_set = 1; ++ ieee->wpax_type_notify = value; ++ spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags); ++ break; ++ ++ default: ++ printk("Unknown WPA param: %d\n",name); ++ ret = -EOPNOTSUPP; ++ } ++ ++ return ret; ++} ++ ++/* implementation borrowed from hostap driver */ ++ ++static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, ++ struct ieee_param *param, int param_len) ++{ ++ int ret = 0; ++ ++ struct ieee80211_crypto_ops *ops; ++ struct ieee80211_crypt_data **crypt; ++ ++ struct ieee80211_security sec = { ++ .flags = 0, ++ }; ++ ++ param->u.crypt.err = 0; ++ param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; ++ ++ if (param_len != ++ (int) ((char *) param->u.crypt.key - (char *) param) + ++ param->u.crypt.key_len) { ++ printk("Len mismatch %d, %d\n", param_len, ++ param->u.crypt.key_len); ++ return -EINVAL; ++ } ++ if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && ++ param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && ++ param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { ++ if (param->u.crypt.idx >= WEP_KEYS) ++ return -EINVAL; ++#ifdef _RTL8187_EXT_PATCH_ ++ crypt = &ieee->cryptlist[0]->crypt[param->u.crypt.idx]; ++#else ++ crypt = &ieee->crypt[param->u.crypt.idx]; ++#endif ++ ++ } else { ++ return -EINVAL; ++ } ++ ++ if (strcmp(param->u.crypt.alg, "none") == 0) { ++ if (crypt) { ++ sec.enabled = 0; ++ // FIXME FIXME ++ //sec.encrypt = 0; ++ sec.level = SEC_LEVEL_0; ++ sec.flags |= SEC_ENABLED | SEC_LEVEL; ++ ieee80211_crypt_delayed_deinit(ieee, crypt); ++ } ++ goto done; ++ } ++ sec.enabled = 1; ++// FIXME FIXME ++// sec.encrypt = 1; ++ sec.flags |= SEC_ENABLED; ++ ++ /* IPW HW cannot build TKIP MIC, host decryption still needed. */ ++ if (!(ieee->host_encrypt || ieee->host_decrypt) && ++ strcmp(param->u.crypt.alg, "TKIP")) ++ goto skip_host_crypt; ++ ++ ops = ieee80211_get_crypto_ops(param->u.crypt.alg); ++ if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { ++ request_module("ieee80211_crypt_wep"); ++ ops = ieee80211_get_crypto_ops(param->u.crypt.alg); ++ } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) { ++ request_module("ieee80211_crypt_tkip"); ++ ops = ieee80211_get_crypto_ops(param->u.crypt.alg); ++ } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) { ++ request_module("ieee80211_crypt_ccmp"); ++ ops = ieee80211_get_crypto_ops(param->u.crypt.alg); ++ } ++ if (ops == NULL) { ++ printk("unknown crypto alg '%s'\n", param->u.crypt.alg); ++ param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG; ++ ret = -EINVAL; ++ goto done; ++ } ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ u8 i; ++ for (i=0; icryptlist[i]->crypt[param->u.crypt.idx]; ++// if (crypt != NULL) printk("crypt not null\n", crypt); ++ ++ *crypt = ieee->cryptlist[i]->crypt[param->u.crypt.idx]; ++#endif ++ if (*crypt == NULL || (*crypt)->ops != ops) { ++ struct ieee80211_crypt_data *new_crypt; ++ ++ ieee80211_crypt_delayed_deinit(ieee, crypt); ++ ++ new_crypt = (struct ieee80211_crypt_data *) ++ kmalloc(sizeof(*new_crypt), GFP_KERNEL); ++ if (new_crypt == NULL) { ++ ret = -ENOMEM; ++ goto done; ++ } ++ memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); ++ new_crypt->ops = ops; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ++ if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) ++#else ++ if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner)) ++#endif ++ new_crypt->priv = ++ new_crypt->ops->init(param->u.crypt.idx); ++ ++ if (new_crypt->priv == NULL) { ++ kfree(new_crypt); ++ param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED; ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ *crypt = new_crypt; ++ } ++ ++ if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key && ++ (*crypt)->ops->set_key(param->u.crypt.key, ++ param->u.crypt.key_len, param->u.crypt.seq, ++ (*crypt)->priv) < 0) { ++ printk("key setting failed\n"); ++ param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED; ++ ret = -EINVAL; ++ goto done; ++ } ++#ifdef _RTL8187_EXT_PATCH_ ++ } ++#endif ++ skip_host_crypt: ++ if (param->u.crypt.set_tx) { ++ ieee->tx_keyidx = param->u.crypt.idx; ++ sec.active_key = param->u.crypt.idx; ++ sec.flags |= SEC_ACTIVE_KEY; ++ } else ++ sec.flags &= ~SEC_ACTIVE_KEY; ++ ++ if (param->u.crypt.alg != NULL) { ++ memcpy(sec.keys[param->u.crypt.idx], ++ param->u.crypt.key, ++ param->u.crypt.key_len); ++ sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len; ++ sec.flags |= (1 << param->u.crypt.idx); ++ ++ if (strcmp(param->u.crypt.alg, "WEP") == 0) { ++ sec.flags |= SEC_LEVEL; ++ sec.level = SEC_LEVEL_1; ++ } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { ++ sec.flags |= SEC_LEVEL; ++ sec.level = SEC_LEVEL_2; ++ } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { ++ sec.flags |= SEC_LEVEL; ++ sec.level = SEC_LEVEL_3; ++ } ++ } ++ done: ++ if (ieee->set_security) ++ ieee->set_security(ieee->dev, &sec); ++#if 1 ++#ifdef _RTL8187_EXT_PATCH_ ++ if (ret != 0)//error out ++ { ++ for (i=0; icryptlist[i]->crypt[param->u.crypt.idx]==NULL){ ++ break; ++ } ++ else{ ++ //if (ieee->cryptlist[i]->crypt[param->u.crypt.idx] != NULL) ++ // { ++ kfree(ieee->cryptlist[i]->crypt[param->u.crypt.idx]); ++ ieee->cryptlist[i]->crypt[param->u.crypt.idx] = NULL; ++ // } ++ // kfree(ieee->cryptlist[i]); ++ // ieee->cryptlist[i] = NULL; ++ } ++ } ++ } ++#endif ++#endif ++ /* Do not reset port if card is in Managed mode since resetting will ++ * generate new IEEE 802.11 authentication which may end up in looping ++ * with IEEE 802.1X. If your hardware requires a reset after WEP ++ * configuration (for example... Prism2), implement the reset_port in ++ * the callbacks structures used to initialize the 802.11 stack. */ ++ if (ieee->reset_on_keychange && ++ ieee->iw_mode != IW_MODE_INFRA && ++ ieee->reset_port && ++ ieee->reset_port(ieee->dev)) { ++ printk("reset_port failed\n"); ++ param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED; ++ return -EINVAL; ++ } ++ ++ return ret; ++} ++ ++int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p) ++{ ++ struct ieee_param *param; ++ int ret=0; ++ ++ down(&ieee->wx_sem); ++ //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length); ++ ++ if (p->length < sizeof(struct ieee_param) || !p->pointer){ ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ param = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL); ++ if (param == NULL){ ++ ret = -ENOMEM; ++ goto out; ++ } ++ if (copy_from_user(param, p->pointer, p->length)) { ++ kfree(param); ++ ret = -EFAULT; ++ goto out; ++ } ++ ++ switch (param->cmd) { ++ ++ case IEEE_CMD_SET_WPA_PARAM: ++ ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name, ++ param->u.wpa_param.value); ++ break; ++ ++ case IEEE_CMD_SET_WPA_IE: ++ ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length); ++ break; ++ ++ case IEEE_CMD_SET_ENCRYPTION: ++ ret = ieee80211_wpa_set_encryption(ieee, param, p->length); ++ break; ++ ++ case IEEE_CMD_MLME: ++ ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command, ++ param->u.mlme.reason_code); ++ break; ++ ++ default: ++ printk("Unknown WPA supplicant request: %d\n",param->cmd); ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ if (ret == 0 && copy_to_user(p->pointer, param, p->length)) ++ ret = -EFAULT; ++ ++ kfree(param); ++out: ++ up(&ieee->wx_sem); ++ ++ return ret; ++} ++ ++void notify_wx_assoc_event(struct ieee80211_device *ieee) ++{ ++ union iwreq_data wrqu; ++ wrqu.ap_addr.sa_family = ARPHRD_ETHER; ++ if (ieee->state == IEEE80211_LINKED) ++ memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN); ++ else ++ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); ++ wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL); ++} ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++EXPORT_SYMBOL(ieee80211_get_beacon); ++EXPORT_SYMBOL(ieee80211_wake_queue); ++EXPORT_SYMBOL(ieee80211_stop_queue); ++EXPORT_SYMBOL(ieee80211_reset_queue); ++EXPORT_SYMBOL(ieee80211_softmac_stop_protocol); ++EXPORT_SYMBOL(ieee80211_softmac_start_protocol); ++EXPORT_SYMBOL(ieee80211_is_shortslot); ++EXPORT_SYMBOL(ieee80211_is_54g); ++EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl); ++EXPORT_SYMBOL(ieee80211_ps_tx_ack); ++EXPORT_SYMBOL(notify_wx_assoc_event); ++EXPORT_SYMBOL(ieee80211_stop_send_beacons); ++EXPORT_SYMBOL(ieee80211_start_send_beacons); ++EXPORT_SYMBOL(ieee80211_start_scan_syncro); ++EXPORT_SYMBOL(ieee80211_start_protocol); ++EXPORT_SYMBOL(ieee80211_stop_protocol); ++EXPORT_SYMBOL(ieee80211_start_scan); ++EXPORT_SYMBOL(ieee80211_stop_scan); ++#ifdef _RTL8187_EXT_PATCH_ ++EXPORT_SYMBOL(ieee80211_ext_issue_assoc_req); ++EXPORT_SYMBOL(ieee80211_ext_issue_disassoc); ++EXPORT_SYMBOL(ieee80211_ext_issue_assoc_rsp); ++EXPORT_SYMBOL(softmac_mgmt_xmit); ++EXPORT_SYMBOL(ieee80211_ext_probe_resp_by_net); ++EXPORT_SYMBOL(ieee80211_stop_scan); ++EXPORT_SYMBOL(ieee80211_ext_send_11s_beacon); ++EXPORT_SYMBOL(ieee80211_rx_auth_rq); ++EXPORT_SYMBOL(ieee80211_associate_step1); ++#endif // _RTL8187_EXT_PATCH_ ++#else ++EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon); ++EXPORT_SYMBOL_NOVERS(ieee80211_wake_queue); ++EXPORT_SYMBOL_NOVERS(ieee80211_stop_queue); ++EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue); ++EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol); ++EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol); ++EXPORT_SYMBOL_NOVERS(ieee80211_is_shortslot); ++EXPORT_SYMBOL_NOVERS(ieee80211_is_54g); ++EXPORT_SYMBOL_NOVERS(ieee80211_wpa_supplicant_ioctl); ++EXPORT_SYMBOL_NOVERS(ieee80211_ps_tx_ack); ++EXPORT_SYMBOL_NOVERS(ieee80211_start_scan); ++EXPORT_SYMBOL_NOVERS(ieee80211_stop_scan); ++#ifdef _RTL8187_EXT_PATCH_ ++EXPORT_SYMBOL_NOVERS(ieee80211_ext_issue_assoc_req); ++EXPORT_SYMBOL_NOVERS(ieee80211_ext_issue_disassoc); ++EXPORT_SYMBOL_NOVERS(ieee80211_ext_issue_assoc_rsp); ++EXPORT_SYMBOL_NOVERS(softmac_mgmt_xmit); ++EXPORT_SYMBOL_NOVERS(ieee80211_ext_probe_resp_by_net); ++EXPORT_SYMBOL_NOVERS(ieee80211_stop_scan); ++EXPORT_SYMBOL_NOVERS(ieee80211_ext_send_11s_beacon); ++EXPORT_SYMBOL_NOVERS(ieee80211_rx_auth_rq); ++EXPORT_SYMBOL(ieee80211_associate_step1); ++#endif // _RTL8187_EXT_PATCH_ ++ ++#endif ++//EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame); +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_softmac_wx.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_softmac_wx.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_softmac_wx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_softmac_wx.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,629 @@ ++/* IEEE 802.11 SoftMAC layer ++ * Copyright (c) 2005 Andrea Merello ++ * ++ * Mostly extracted from the rtl8180-sa2400 driver for the ++ * in-kernel generic ieee802.11 stack. ++ * ++ * Some pieces of code might be stolen from ipw2100 driver ++ * copyright of who own it's copyright ;-) ++ * ++ * PS wx handler mostly stolen from hostap, copyright who ++ * own it's copyright ;-) ++ * ++ * released under the GPL ++ */ ++ ++ ++#include "ieee80211.h" ++#ifdef ENABLE_DOT11D ++#include "dot11d.h" ++#endif ++ ++/* FIXME: add A freqs */ ++ ++const long ieee80211_wlan_frequencies[] = { ++ 2412, 2417, 2422, 2427, ++ 2432, 2437, 2442, 2447, ++ 2452, 2457, 2462, 2467, ++ 2472, 2484 ++}; ++ ++ ++int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b) ++{ ++ int ret; ++ struct iw_freq *fwrq = & wrqu->freq; ++ ++ down(&ieee->wx_sem); ++ ++ if(ieee->iw_mode == IW_MODE_INFRA){ ++ ret = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ /* if setting by freq convert to channel */ ++ if (fwrq->e == 1) { ++ if ((fwrq->m >= (int) 2.412e8 && ++ fwrq->m <= (int) 2.487e8)) { ++ int f = fwrq->m / 100000; ++ int c = 0; ++ ++ while ((c < 14) && (f != ieee80211_wlan_frequencies[c])) ++ c++; ++ ++ /* hack to fall through */ ++ fwrq->e = 0; ++ fwrq->m = c + 1; ++ } ++ } ++ ++ if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1 ){ ++ ret = -EOPNOTSUPP; ++ goto out; ++ ++ }else { /* Set the channel */ ++ ++#ifdef ENABLE_DOT11D ++ if(!IsLegalChannel(ieee, fwrq->m) ) ++ { ++ printk("channel(%d). is invalide\n", fwrq->m); ++ ret = -EOPNOTSUPP; ++ goto out; ++ } ++ else ++ { ++ if(ieee->iw_mode == IW_MODE_ADHOC) ++ { ++ if(ieee->MinPassiveChnlNum != MAX_CHANNEL_NUMBER+1) ++ { ++ if(fwrq->m >= ieee->MinPassiveChnlNum) ++ { ++ ret = -EOPNOTSUPP; ++ goto out; ++ } ++ } ++ } ++ } ++#endif ++ ieee->current_network.channel = fwrq->m; ++ ieee->set_chan(ieee->dev, ieee->current_network.channel); ++ ++ if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) ++ if(ieee->state == IEEE80211_LINKED){ ++ ++ ieee80211_stop_send_beacons(ieee); ++ ieee80211_start_send_beacons(ieee); ++ } ++ } ++ ++ ret = 0; ++out: ++ up(&ieee->wx_sem); ++ return ret; ++} ++ ++ ++int ieee80211_wx_get_freq(struct ieee80211_device *ieee, ++ struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b) ++{ ++ struct iw_freq *fwrq = & wrqu->freq; ++ ++ if (ieee->current_network.channel == 0) ++ return -1; ++ ++ fwrq->m = ieee->current_network.channel; ++ fwrq->e = 0; ++ ++ return 0; ++} ++ ++int ieee80211_wx_get_wap(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ unsigned long flags; ++ ++ wrqu->ap_addr.sa_family = ARPHRD_ETHER; ++ ++ if (ieee->iw_mode == IW_MODE_MONITOR) ++ return -1; ++ ++ /* We want avoid to give to the user inconsistent infos*/ ++ spin_lock_irqsave(&ieee->lock, flags); ++ ++ if (ieee->state != IEEE80211_LINKED && ++ ieee->state != IEEE80211_LINKED_SCANNING && ++ ieee->wap_set == 0) ++ ++ memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); ++ else ++ memcpy(wrqu->ap_addr.sa_data, ++ ieee->current_network.bssid, ETH_ALEN); ++ ++ spin_unlock_irqrestore(&ieee->lock, flags); ++ ++ return 0; ++} ++ ++ ++int ieee80211_wx_set_wap(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *awrq, ++ char *extra) ++{ ++ ++ int ret = 0; ++ u8 zero[] = {0,0,0,0,0,0}; ++ unsigned long flags; ++ ++ short ifup = ieee->proto_started;//dev->flags & IFF_UP; ++ struct sockaddr *temp = (struct sockaddr *)awrq; ++ ++ ieee->sync_scan_hurryup = 1; ++ ++ down(&ieee->wx_sem); ++ /* use ifconfig hw ether */ ++ if (ieee->iw_mode == IW_MODE_MASTER){ ++ ret = -1; ++ goto out; ++ } ++ ++ if (temp->sa_family != ARPHRD_ETHER){ ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (ifup) ++ ieee80211_stop_protocol(ieee); ++ ++ /* just to avoid to give inconsistent infos in the ++ * get wx method. not really needed otherwise ++ */ ++ spin_lock_irqsave(&ieee->lock, flags); ++ ++ memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); ++ ieee->wap_set = memcmp(temp->sa_data, zero,ETH_ALEN)!=0; ++ ++ spin_unlock_irqrestore(&ieee->lock, flags); ++ ++ if (ifup) ++ ieee80211_start_protocol(ieee); ++ ++out: ++ up(&ieee->wx_sem); ++ return ret; ++} ++ ++ int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b) ++{ ++ int len,ret = 0; ++ unsigned long flags; ++ ++ if (ieee->iw_mode == IW_MODE_MONITOR) ++ return -1; ++ ++ /* We want avoid to give to the user inconsistent infos*/ ++ spin_lock_irqsave(&ieee->lock, flags); ++ ++ if (ieee->current_network.ssid[0] == '\0' || ++ ieee->current_network.ssid_len == 0){ ++ ret = -1; ++ goto out; ++ } ++ ++ if (ieee->state != IEEE80211_LINKED && ++ ieee->state != IEEE80211_LINKED_SCANNING && ++ ieee->ssid_set == 0){ ++ ret = -1; ++ goto out; ++ } ++ len = ieee->current_network.ssid_len; ++ wrqu->essid.length = len; ++ strncpy(b,ieee->current_network.ssid,len); ++ wrqu->essid.flags = 1; ++ ++out: ++ spin_unlock_irqrestore(&ieee->lock, flags); ++ ++ return ret; ++ ++} ++ ++int ieee80211_wx_set_rate(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ ++ u32 target_rate = wrqu->bitrate.value; ++ ++ ieee->rate = target_rate/100000; ++ //FIXME: we might want to limit rate also in management protocols. ++ return 0; ++} ++ ++ ++ ++int ieee80211_wx_get_rate(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ ++ wrqu->bitrate.value = ieee->rate * 100000; ++ ++ return 0; ++} ++ ++int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b) ++{ ++ ++ ieee->sync_scan_hurryup = 1; ++ ++ down(&ieee->wx_sem); ++ //printk("=======>%s\n", __func__); ++ ++ if (wrqu->mode == ieee->iw_mode) ++ goto out; ++ ++ if (wrqu->mode == IW_MODE_MONITOR){ ++ ++ ieee->dev->type = ARPHRD_IEEE80211; ++ }else{ ++ ieee->dev->type = ARPHRD_ETHER; ++ } ++ ++ if (!ieee->proto_started){ ++ ieee->iw_mode = wrqu->mode; ++ }else{ ++ ieee80211_stop_protocol(ieee); ++ ieee->iw_mode = wrqu->mode; ++ ieee80211_start_protocol(ieee); ++ } ++ ++out: ++ up(&ieee->wx_sem); ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++void ieee80211_wx_sync_scan_wq(struct work_struct *work) ++{ ++ struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wx_sync_scan_wq); ++#else ++void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee) ++{ ++#endif ++ short chan; ++ ++ chan = ieee->current_network.channel; ++ ++ netif_carrier_off(ieee->dev); ++ ++ if (ieee->data_hard_stop) ++ ieee->data_hard_stop(ieee->dev); ++ ++ ieee80211_stop_send_beacons(ieee); ++ ++ ieee->state = IEEE80211_LINKED_SCANNING; ++ ieee->link_change(ieee->dev); ++ ++ ieee80211_start_scan_syncro(ieee); ++ ++ ieee->set_chan(ieee->dev, chan); ++ ++ ieee->state = IEEE80211_LINKED; ++ ieee->link_change(ieee->dev); ++ ++ if (ieee->data_hard_resume) ++ ieee->data_hard_resume(ieee->dev); ++ ++ if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) ++ ieee80211_start_send_beacons(ieee); ++ ++ netif_carrier_on(ieee->dev); ++ ++ up(&ieee->wx_sem); ++ ++} ++ ++int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b) ++{ ++ int ret = 0; ++ ++ down(&ieee->wx_sem); ++ ++ if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)){ ++ ret = -1; ++ goto out; ++ } ++ ++ if ( ieee->state == IEEE80211_LINKED){ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ queue_work(ieee->wq, &ieee->wx_sync_scan_wq); ++#else ++ schedule_task(&ieee->wx_sync_scan_wq); ++#endif ++ /* intentionally forget to up sem */ ++ return 0; ++ } ++ ++out: ++ up(&ieee->wx_sem); ++ return ret; ++} ++ ++int ieee80211_wx_set_essid(struct ieee80211_device *ieee, ++ struct iw_request_info *a, ++ union iwreq_data *wrqu, char *extra) ++{ ++ ++ int ret=0,len; ++ short proto_started; ++ unsigned long flags; ++ ++ ieee->sync_scan_hurryup = 1; ++ ++ down(&ieee->wx_sem); ++ ++ //printk("=======>%s\n", __func__); ++ proto_started = ieee->proto_started; ++ ++ if (wrqu->essid.length > IW_ESSID_MAX_SIZE){ ++ ret= -E2BIG; ++ goto out; ++ } ++ ++ if (ieee->iw_mode == IW_MODE_MONITOR){ ++ ret= -1; ++ goto out; ++ } ++ ++ if(proto_started){ ++ ieee80211_stop_protocol(ieee); ++ } ++ ++ /* this is just to be sure that the GET wx callback ++ * has consisten infos. not needed otherwise ++ */ ++ spin_lock_irqsave(&ieee->lock, flags); ++ ++ if (wrqu->essid.flags && wrqu->essid.length) { ++ len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ strncpy(ieee->current_network.ssid, extra, len); ++ ieee->current_network.ssid_len = len; ++#else ++ strncpy(ieee->current_network.ssid, extra, len+1); ++ ieee->current_network.ssid_len = len+1; ++#endif ++ ieee->ssid_set = 1; ++ //YJ,add,080819,for hidden ap ++ if(len == 0){ ++ memset(ieee->current_network.bssid, 0, ETH_ALEN); ++ ieee->current_network.capability = 0; ++ } ++ //YJ,add,080819,for hidden ap,end ++ } ++ else{ ++ ieee->ssid_set = 0; ++ ieee->current_network.ssid[0] = '\0'; ++ ieee->current_network.ssid_len = 0; ++ } ++ ++ spin_unlock_irqrestore(&ieee->lock, flags); ++ ++ if (proto_started){ ++ ieee80211_start_protocol(ieee); ++ } ++out: ++ up(&ieee->wx_sem); ++ return ret; ++} ++ ++ int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b) ++{ ++ ++ wrqu->mode = ieee->iw_mode; ++ return 0; ++} ++ ++ int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ ++ int *parms = (int *)extra; ++ int enable = (parms[0] > 0); ++ short prev = ieee->raw_tx; ++ ++ down(&ieee->wx_sem); ++ ++ if(enable) ++ ieee->raw_tx = 1; ++ else ++ ieee->raw_tx = 0; ++ ++ printk(KERN_INFO"raw TX is %s\n", ++ ieee->raw_tx ? "enabled" : "disabled"); ++ ++ if(ieee->iw_mode == IW_MODE_MONITOR) ++ { ++ if(prev == 0 && ieee->raw_tx){ ++ if (ieee->data_hard_resume) ++ ieee->data_hard_resume(ieee->dev); ++ ++ netif_carrier_on(ieee->dev); ++ } ++ ++ if(prev && ieee->raw_tx == 1) ++ netif_carrier_off(ieee->dev); ++ } ++ ++ up(&ieee->wx_sem); ++ ++ return 0; ++} ++ ++int ieee80211_wx_get_name(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ strcpy(wrqu->name, "802.11"); ++ if(ieee->modulation & IEEE80211_CCK_MODULATION){ ++ strcat(wrqu->name, "b"); ++ if(ieee->modulation & IEEE80211_OFDM_MODULATION) ++ strcat(wrqu->name, "/g"); ++ }else if(ieee->modulation & IEEE80211_OFDM_MODULATION) ++ strcat(wrqu->name, "g"); ++ ++ if((ieee->state == IEEE80211_LINKED) || ++ (ieee->state == IEEE80211_LINKED_SCANNING)) ++ strcat(wrqu->name," linked"); ++ else if(ieee->state != IEEE80211_NOLINK) ++ strcat(wrqu->name," link.."); ++ ++ ++ return 0; ++} ++ ++ ++/* this is mostly stolen from hostap */ ++int ieee80211_wx_set_power(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ int ret = 0; ++ ++ if( ++ (!ieee->sta_wake_up) || ++ (!ieee->ps_request_tx_ack) || ++ (!ieee->enter_sleep_state) || ++ (!ieee->ps_is_queue_empty)){ ++ ++ printk("ERROR. PS mode is tryied to be use but\ ++driver missed a callback\n\n"); ++ ++ return -1; ++ } ++ ++ down(&ieee->wx_sem); ++ ++ if (wrqu->power.disabled){ ++ ieee->ps = IEEE80211_PS_DISABLED; ++ ++ goto exit; ++ } ++ switch (wrqu->power.flags & IW_POWER_MODE) { ++ case IW_POWER_UNICAST_R: ++ ieee->ps = IEEE80211_PS_UNICAST; ++ ++ break; ++ case IW_POWER_ALL_R: ++ ieee->ps = IEEE80211_PS_UNICAST | IEEE80211_PS_MBCAST; ++ break; ++ ++ case IW_POWER_ON: ++ ieee->ps = IEEE80211_PS_DISABLED; ++ break; ++ ++ default: ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (wrqu->power.flags & IW_POWER_TIMEOUT) { ++ ++ ieee->ps_timeout = wrqu->power.value / 1000; ++ printk("Timeout %d\n",ieee->ps_timeout); ++ } ++ ++ if (wrqu->power.flags & IW_POWER_PERIOD) { ++ ++ ret = -EOPNOTSUPP; ++ goto exit; ++ //wrq->value / 1024; ++ ++ } ++exit: ++ up(&ieee->wx_sem); ++ return ret; ++ ++} ++ ++/* this is stolen from hostap */ ++int ieee80211_wx_get_power(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ int ret =0; ++ ++ down(&ieee->wx_sem); ++ ++ if(ieee->ps == IEEE80211_PS_DISABLED){ ++ wrqu->power.disabled = 1; ++ goto exit; ++ } ++ ++ wrqu->power.disabled = 0; ++ ++// if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { ++ wrqu->power.flags = IW_POWER_TIMEOUT; ++ wrqu->power.value = ieee->ps_timeout * 1000; ++// } else { ++// ret = -EOPNOTSUPP; ++// goto exit; ++ //wrqu->power.flags = IW_POWER_PERIOD; ++ //wrqu->power.value = ieee->current_network.dtim_period * ++ // ieee->current_network.beacon_interval * 1024; ++// } ++ ++ ++ if (ieee->ps & IEEE80211_PS_MBCAST) ++ wrqu->power.flags |= IW_POWER_ALL_R; ++ else ++ wrqu->power.flags |= IW_POWER_UNICAST_R; ++ ++exit: ++ up(&ieee->wx_sem); ++ return ret; ++ ++} ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++EXPORT_SYMBOL(ieee80211_wx_get_essid); ++EXPORT_SYMBOL(ieee80211_wx_set_essid); ++EXPORT_SYMBOL(ieee80211_wx_set_rate); ++EXPORT_SYMBOL(ieee80211_wx_get_rate); ++EXPORT_SYMBOL(ieee80211_wx_set_wap); ++EXPORT_SYMBOL(ieee80211_wx_get_wap); ++EXPORT_SYMBOL(ieee80211_wx_set_mode); ++EXPORT_SYMBOL(ieee80211_wx_get_mode); ++EXPORT_SYMBOL(ieee80211_wx_set_scan); ++EXPORT_SYMBOL(ieee80211_wx_get_freq); ++EXPORT_SYMBOL(ieee80211_wx_set_freq); ++EXPORT_SYMBOL(ieee80211_wx_set_rawtx); ++EXPORT_SYMBOL(ieee80211_wx_get_name); ++EXPORT_SYMBOL(ieee80211_wx_set_power); ++EXPORT_SYMBOL(ieee80211_wx_get_power); ++EXPORT_SYMBOL(ieee80211_wlan_frequencies); ++#else ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_essid); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_essid); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_rate); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_rate); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_wap); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_wap); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_mode); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_mode); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_scan); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_freq); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_freq); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_rawtx); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_name); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_power); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_power); ++EXPORT_SYMBOL_NOVERS(ieee80211_wlan_frequencies); ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_tx.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_tx.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_tx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_tx.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,876 @@ ++/****************************************************************************** ++ ++ Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. ++ ++ This program is free software; you can redistribute it and/or modify it ++ under the terms of version 2 of the GNU General Public License as ++ published by the Free Software Foundation. ++ ++ This program is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., 59 ++ Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++ The full GNU General Public License is included in this distribution in the ++ file called LICENSE. ++ ++ Contact Information: ++ James P. Ketrenos ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++****************************************************************************** ++ ++ Few modifications for Realtek's Wi-Fi drivers by ++ Andrea Merello ++ ++ A special thanks goes to Realtek for their support ! ++ ++******************************************************************************/ ++ ++#include ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ieee80211.h" ++ ++ ++/* ++ ++ ++802.11 Data Frame ++ ++ ++802.11 frame_contorl for data frames - 2 bytes ++ ,-----------------------------------------------------------------------------------------. ++bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | ++ |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| ++val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x | ++ |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| ++desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep | ++ | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | | ++ '-----------------------------------------------------------------------------------------' ++ /\ ++ | ++802.11 Data Frame | ++ ,--------- 'ctrl' expands to >-----------' ++ | ++ ,--'---,-------------------------------------------------------------. ++Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | ++ |------|------|---------|---------|---------|------|---------|------| ++Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs | ++ | | tion | (BSSID) | | | ence | data | | ++ `--------------------------------------------------| |------' ++Total: 28 non-data bytes `----.----' ++ | ++ .- 'Frame data' expands to <---------------------------' ++ | ++ V ++ ,---------------------------------------------------. ++Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 | ++ |------|------|---------|----------|------|---------| ++Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP | ++ | DSAP | SSAP | | | | Packet | ++ | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | | ++ `-----------------------------------------| | ++Total: 8 non-data bytes `----.----' ++ | ++ .- 'IP Packet' expands, if WEP enabled, to <--' ++ | ++ V ++ ,-----------------------. ++Bytes | 4 | 0-2296 | 4 | ++ |-----|-----------|-----| ++Desc. | IV | Encrypted | ICV | ++ | | IP Packet | | ++ `-----------------------' ++Total: 8 non-data bytes ++ ++ ++802.3 Ethernet Data Frame ++ ++ ,-----------------------------------------. ++Bytes | 6 | 6 | 2 | Variable | 4 | ++ |-------|-------|------|-----------|------| ++Desc. | Dest. | Source| Type | IP Packet | fcs | ++ | MAC | MAC | | | | ++ `-----------------------------------------' ++Total: 18 non-data bytes ++ ++In the event that fragmentation is required, the incoming payload is split into ++N parts of size ieee->fts. The first fragment contains the SNAP header and the ++remaining packets are just data. ++ ++If encryption is enabled, each fragment payload size is reduced by enough space ++to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP) ++So if you have 1500 bytes of payload with ieee->fts set to 500 without ++encryption it will take 3 frames. With WEP it will take 4 frames as the ++payload of each frame is reduced to 492 bytes. ++ ++* SKB visualization ++* ++* ,- skb->data ++* | ++* | ETHERNET HEADER ,-<-- PAYLOAD ++* | | 14 bytes from skb->data ++* | 2 bytes for Type --> ,T. | (sizeof ethhdr) ++* | | | | ++* |,-Dest.--. ,--Src.---. | | | ++* | 6 bytes| | 6 bytes | | | | ++* v | | | | | | ++* 0 | v 1 | v | v 2 ++* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 ++* ^ | ^ | ^ | ++* | | | | | | ++* | | | | `T' <---- 2 bytes for Type ++* | | | | ++* | | '---SNAP--' <-------- 6 bytes for SNAP ++* | | ++* `-IV--' <-------------------- 4 bytes for IV (WEP) ++* ++* SNAP HEADER ++* ++*/ ++ ++static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; ++static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; ++ ++static inline int ieee80211_put_snap(u8 *data, u16 h_proto) ++{ ++ struct ieee80211_snap_hdr *snap; ++ u8 *oui; ++ ++ snap = (struct ieee80211_snap_hdr *)data; ++ snap->dsap = 0xaa; ++ snap->ssap = 0xaa; ++ snap->ctrl = 0x03; ++ ++ if (h_proto == 0x8137 || h_proto == 0x80f3) ++ oui = P802_1H_OUI; ++ else ++ oui = RFC1042_OUI; ++ snap->oui[0] = oui[0]; ++ snap->oui[1] = oui[1]; ++ snap->oui[2] = oui[2]; ++ ++ *(u16 *)(data + SNAP_SIZE) = htons(h_proto); ++ ++ return SNAP_SIZE + sizeof(u16); ++} ++ ++int ieee80211_encrypt_fragment( ++ struct ieee80211_device *ieee, ++ struct sk_buff *frag, ++ int hdr_len) ++{ ++ struct ieee80211_crypt_data* crypt = NULL;//ieee->crypt[ieee->tx_keyidx]; ++ int res;//, i; ++// printk("====>wwwwww%s():ieee:%x, hdr_len:%d\n", __FUNCTION__, ieee, hdr_len); ++/* printk("\n%s(), hdr_len:%d\n", __FUNCTION__, hdr_len); ++ for (i = 0; i < 48; i++) { ++ if (i % 16 == 0) printk("\n\t"); ++ printk("%2x ", *(frag->data+i)); ++ } ++*/ ++ ++#ifdef _RTL8187_EXT_PATCH_ ++#if 0 ++ i = ieee80211_find_MP(ieee, ((struct ieee80211_hdr*) frag->data)->addr1); ++ if (i== -1){ ++ printk("error find MP entry in %s()\n", __FUNCTION__); ++ return i; ++ } ++ // printk("%s():"MAC_FMT", find in index:%d\n", __FUNCTION__, MAC_ARG(((struct ieee80211_hdr*)frag->data)->addr1), i); ++#endif ++// crypt = ieee->cryptlist[MAX_MP-1]->crypt[ieee->tx_keyidx]; ++ crypt = ieee->cryptlist[0]->crypt[ieee->tx_keyidx]; ++#else ++ crypt = ieee->crypt[ieee->tx_keyidx]; ++#endif ++ /*added to care about null crypt condition, to solve that system hangs when shared keys error*/ ++ if (!crypt || !crypt->ops) ++ return -1; ++ ++#ifdef CONFIG_IEEE80211_CRYPT_TKIP ++ struct ieee80211_hdr *header; ++ ++ if (ieee->tkip_countermeasures && ++ crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) { ++ header = (struct ieee80211_hdr *) frag->data; ++ if (net_ratelimit()) { ++ printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " ++ "TX packet to " MAC_FMT "\n", ++ ieee->dev->name, MAC_ARG(header->addr1)); ++ } ++ return -1; ++ } ++#endif ++ /* To encrypt, frame format is: ++ * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */ ++ ++ // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption. ++ /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so ++ * call both MSDU and MPDU encryption functions from here. */ ++ atomic_inc(&crypt->refcnt); ++ res = 0; ++ if (crypt->ops->encrypt_msdu) ++ res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv); ++ if (res == 0 && crypt->ops->encrypt_mpdu) ++ res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); ++ atomic_dec(&crypt->refcnt); ++ if (res < 0) { ++ printk(KERN_INFO "%s: Encryption failed: len=%d.\n", ++ ieee->dev->name, frag->len); ++ ieee->ieee_stats.tx_discards++; ++ return -1; ++ } ++ ++ return 0; ++} ++ ++ ++void ieee80211_txb_free(struct ieee80211_txb *txb) { ++ int i; ++ if (unlikely(!txb)) ++ return; ++ for (i = 0; i < txb->nr_frags; i++) ++ if (txb->fragments[i]) ++ dev_kfree_skb_any(txb->fragments[i]); ++ kfree(txb); ++} ++ ++struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, ++ int gfp_mask) ++{ ++ struct ieee80211_txb *txb; ++ int i; ++ txb = kmalloc( ++ sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags), ++ gfp_mask); ++ if (!txb) ++ return NULL; ++ ++ memset(txb, 0, sizeof(struct ieee80211_txb)); ++ txb->nr_frags = nr_frags; ++ txb->frag_size = txb_size; ++ ++ for (i = 0; i < nr_frags; i++) { ++ txb->fragments[i] = dev_alloc_skb(txb_size); ++ if (unlikely(!txb->fragments[i])) { ++ i--; ++ break; ++ } ++ } ++ if (unlikely(i != nr_frags)) { ++ while (i >= 0) ++ dev_kfree_skb_any(txb->fragments[i--]); ++ kfree(txb); ++ return NULL; ++ } ++ return txb; ++} ++ ++// Classify the to-be send data packet ++// Need to acquire the sent queue index. ++static int ++ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network) ++{ ++ struct ether_header *eh = (struct ether_header*)skb->data; ++ unsigned int wme_UP = 0; ++ ++ if(!network->QoS_Enable) { ++ skb->priority = 0; ++ return(wme_UP); ++ } ++ ++ if(eh->ether_type == __constant_htons(ETHERTYPE_IP)) { ++ const struct iphdr *ih = (struct iphdr*)(skb->data + \ ++ sizeof(struct ether_header)); ++ wme_UP = (ih->tos >> 5)&0x07; ++ } else if (vlan_tx_tag_present(skb)) {//vtag packet ++#ifndef VLAN_PRI_SHIFT ++#define VLAN_PRI_SHIFT 13 /* Shift to find VLAN user priority */ ++#define VLAN_PRI_MASK 7 /* Mask for user priority bits in VLAN */ ++#endif ++ u32 tag = vlan_tx_tag_get(skb); ++ wme_UP = (tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; ++ } else if(ETH_P_PAE == ntohs(((struct ethhdr *)skb->data)->h_proto)) { ++ //printk(KERN_WARNING "type = normal packet\n"); ++ wme_UP = 7; ++ } ++ skb->priority = wme_UP; ++/* ++ if (network->QoS_Enable) { ++ skb->priority = wme_UP; ++ }else { ++ skb->priority = 0; ++ } ++*/ ++ return(wme_UP); ++} ++ ++#ifdef _RTL8187_EXT_PATCH_ ++// based on part of ieee80211_xmit. Mainly allocate txb. ieee->lock is held ++struct ieee80211_txb *ieee80211_ext_alloc_txb(struct sk_buff *skb, struct net_device *dev, struct ieee80211_hdr_3addr *header, int hdr_len, u8 isQoS, u16 *pQOS_ctl, int isEncrypt, struct ieee80211_crypt_data* crypt) ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) ++ struct ieee80211_device *ieee = netdev_priv(dev); ++#else ++ struct ieee80211_device *ieee = (struct ieee80211_device *)dev->priv; ++#endif ++ struct ieee80211_txb *txb = NULL; ++ struct ieee80211_hdr_3addr *frag_hdr; ++ int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; ++ int ether_type; ++ int bytes, QOS_ctl; ++ struct sk_buff *skb_frag; ++ ++ ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); ++ ++ /* Advance the SKB to the start of the payload */ ++ skb_pull(skb, sizeof(struct ethhdr)); ++ ++ /* Determine total amount of storage required for TXB packets */ ++ bytes = skb->len + SNAP_SIZE + sizeof(u16); ++ ++ /* Determine fragmentation size based on destination (multicast ++ * and broadcast are not fragmented) */ ++ // if (is_multicast_ether_addr(dest) || ++ // is_broadcast_ether_addr(dest)) { ++ if (is_multicast_ether_addr(header->addr1) || ++ is_broadcast_ether_addr(header->addr1)) { ++ frag_size = MAX_FRAG_THRESHOLD; ++ QOS_ctl = QOS_CTL_NOTCONTAIN_ACK; ++ } ++ else { ++ //printk(KERN_WARNING "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&frag_size = %d\n", frag_size); ++ frag_size = ieee->fts;//default:392 ++ QOS_ctl = 0; ++ } ++ ++ if(isQoS) { ++ QOS_ctl |= skb->priority; //set in the ieee80211_classify ++ *pQOS_ctl = cpu_to_le16(QOS_ctl); ++ } ++ //printk(KERN_WARNING "header size = %d, QOS_ctl = %x\n", hdr_len,QOS_ctl); ++ /* Determine amount of payload per fragment. Regardless of if ++ * this stack is providing the full 802.11 header, one will ++ * eventually be affixed to this fragment -- so we must account for ++ * it when determining the amount of payload space. */ ++ //bytes_per_frag = frag_size - (IEEE80211_3ADDR_LEN + (ieee->current_network->QoS_Enable ? 2:0)); ++ bytes_per_frag = frag_size - hdr_len; ++ if (ieee->config & ++ (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) ++ bytes_per_frag -= IEEE80211_FCS_LEN; ++ ++ /* Each fragment may need to have room for encryptiong pre/postfix */ ++ if (isEncrypt) ++ bytes_per_frag -= crypt->ops->extra_prefix_len + ++ crypt->ops->extra_postfix_len; ++ ++ /* Number of fragments is the total bytes_per_frag / ++ * payload_per_fragment */ ++ nr_frags = bytes / bytes_per_frag; ++ bytes_last_frag = bytes % bytes_per_frag; ++ if (bytes_last_frag) ++ nr_frags++; ++ else ++ bytes_last_frag = bytes_per_frag; ++ ++ /* When we allocate the TXB we allocate enough space for the reserve ++ * and full fragment bytes (bytes_per_frag doesn't include prefix, ++ * postfix, header, FCS, etc.) */ ++ txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC); ++ if (unlikely(!txb)) { ++ printk(KERN_WARNING "%s: Could not allocate TXB\n", ++ ieee->dev->name); ++ return NULL; ++ } ++ txb->encrypted = isEncrypt; ++ txb->payload_size = bytes; ++ ++ for (i = 0; i < nr_frags; i++) { ++ skb_frag = txb->fragments[i]; ++ skb_frag->priority = UP2AC(skb->priority); ++ if (isEncrypt) ++ skb_reserve(skb_frag, crypt->ops->extra_prefix_len); ++ ++ frag_hdr = (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len); ++ memcpy(frag_hdr, (void *)header, hdr_len); ++ ++ /* If this is not the last fragment, then add the MOREFRAGS ++ * bit to the frame control */ ++ if (i != nr_frags - 1) { ++ frag_hdr->frame_ctl = cpu_to_le16( ++ header->frame_ctl | IEEE80211_FCTL_MOREFRAGS); ++ bytes = bytes_per_frag; ++ ++ } else { ++ /* The last fragment takes the remaining length */ ++ bytes = bytes_last_frag; ++ } ++ ++ frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); ++ //frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl<<4 | i); ++ // ++ ++ /* Put a SNAP header on the first fragment */ ++ if (i == 0) { ++ ieee80211_put_snap( ++ skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), ether_type); ++ bytes -= SNAP_SIZE + sizeof(u16); ++ } ++ ++ memcpy(skb_put(skb_frag, bytes), skb->data, bytes); ++ ++ /* Advance the SKB... */ ++ skb_pull(skb, bytes); ++ ++ /* Encryption routine will move the header forward in order ++ * to insert the IV between the header and the payload */ ++ if (isEncrypt) ++ ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); ++ if (ieee->config & ++ (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) ++ skb_put(skb_frag, 4); ++ } ++ // Advance sequence number in data frame. ++ //printk(KERN_WARNING "QoS Enalbed? %s\n", ieee->current_network.QoS_Enable?"Y":"N"); ++ if (ieee->seq_ctrl[0] == 0xFFF) ++ ieee->seq_ctrl[0] = 0; ++ else ++ ieee->seq_ctrl[0]++; ++ // stanley, just for debug ++/* ++{ ++ int j=0; ++ for(j=0;jfragments[j]; ++ printk("send(%d): ", j); ++ for (i=0;ilen;i++) ++ printk("%02X ", skb->data[i]&0xff); ++ printk("\n"); ++ } ++} ++*/ ++ ++ return txb; ++} ++ ++ ++// based on part of ieee80211_xmit. Mainly allocate txb. ieee->lock is held ++// Assume no encryption, no FCS computing ++struct ieee80211_txb *ieee80211_ext_reuse_txb(struct sk_buff *skb, struct net_device *dev, struct ieee80211_hdr_3addr *header, int hdr_len, u8 isQoS, u16 *pQOS_ctl, int isEncrypt, struct ieee80211_crypt_data* crypt) ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) ++ struct ieee80211_device *ieee = netdev_priv(dev); ++#else ++ struct ieee80211_device *ieee = (struct ieee80211_device *)dev->priv; ++#endif ++ struct ieee80211_txb *txb = NULL; ++ struct ieee80211_hdr_3addr *frag_hdr; ++ int ether_type; ++ int bytes, QOS_ctl; ++ ++ ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); ++ ++ /* Advance the SKB to the start of the payload */ ++ skb_pull(skb, sizeof(struct ethhdr)); ++ ++ /* Determine total amount of storage required for TXB packets */ ++ bytes = skb->len + SNAP_SIZE + sizeof(u16); ++ ++ if (is_multicast_ether_addr(header->addr1) || ++ is_broadcast_ether_addr(header->addr1)) { ++ QOS_ctl = QOS_CTL_NOTCONTAIN_ACK; ++ } ++ else { ++ QOS_ctl = 0; ++ } ++ ++ if(isQoS) { ++ QOS_ctl |= skb->priority; //set in the ieee80211_classify ++ *pQOS_ctl = cpu_to_le16(QOS_ctl); ++ } ++ ++ txb = kmalloc( sizeof(struct ieee80211_txb) + sizeof(u8*), GFP_ATOMIC ); ++ if (unlikely(!txb)) { ++ printk(KERN_WARNING "%s: Could not allocate TXB\n", ++ ieee->dev->name); ++ return NULL; ++ } ++ ++ txb->nr_frags = 1; ++ txb->frag_size = bytes; ++ txb->encrypted = isEncrypt; ++ txb->payload_size = bytes; ++ ++ txb->fragments[0] = skb; ++ ieee80211_put_snap( ++ skb_push(skb, SNAP_SIZE + sizeof(u16)), ether_type); ++ frag_hdr = (struct ieee80211_hdr_3addr *)skb_push(skb, hdr_len); ++ memcpy(frag_hdr, (void *)header, hdr_len); ++ frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | 0); ++ skb->priority = UP2AC(skb->priority); ++ if(isEncrypt) ++ ieee80211_encrypt_fragment(ieee,skb,hdr_len); ++ ++ // Advance sequence number in data frame. ++ //printk(KERN_WARNING "QoS Enalbed? %s\n", ieee->current_network.QoS_Enable?"Y":"N"); ++ if (ieee->seq_ctrl[0] == 0xFFF) ++ ieee->seq_ctrl[0] = 0; ++ else ++ ieee->seq_ctrl[0]++; ++ ++ return txb; ++} ++ ++#endif // _RTL8187_EXT_PATCH_ ++ ++/* SKBs are added to the ieee->tx_queue. */ ++int ieee80211_xmit(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) ++ struct ieee80211_device *ieee = netdev_priv(dev); ++#else ++ struct ieee80211_device *ieee = (struct ieee80211_device *)dev->priv; ++#endif ++ struct ieee80211_txb *txb = NULL; ++ struct ieee80211_hdr_3addr_QOS *frag_hdr; ++ int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; ++ unsigned long flags; ++ struct net_device_stats *stats = &ieee->stats; ++ int ether_type, encrypt; ++ int bytes, fc, QOS_ctl, hdr_len; ++ struct sk_buff *skb_frag; ++ //struct ieee80211_hdr header = { /* Ensure zero initialized */ ++ // .duration_id = 0, ++ // .seq_ctl = 0 ++ //}; ++ struct ieee80211_hdr_3addr_QOS header = { /* Ensure zero initialized */ ++ .duration_id = 0, ++ .seq_ctl = 0, ++ .QOS_ctl = 0 ++ }; ++ u8 dest[ETH_ALEN], src[ETH_ALEN]; ++ ++ struct ieee80211_crypt_data* crypt; ++ ++ //printk(KERN_WARNING "upper layer packet!\n"); ++ spin_lock_irqsave(&ieee->lock, flags); ++ ++ /* If there is no driver handler to take the TXB, dont' bother ++ * creating it... */ ++ if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))|| ++ ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { ++ printk(KERN_WARNING "%s: No xmit handler.\n", ++ ieee->dev->name); ++ goto success; ++ } ++ ++ ieee80211_classify(skb,&ieee->current_network); ++ if(likely(ieee->raw_tx == 0)){ ++ ++ if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { ++ printk(KERN_WARNING "%s: skb too small (%d).\n", ++ ieee->dev->name, skb->len); ++ goto success; ++ } ++ ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ // note, skb->priority which was set by ieee80211_classify, and used by physical tx ++ if((ieee->iw_mode == ieee->iw_ext_mode) && (ieee->ext_patch_ieee80211_xmit)) ++ { ++ txb = ieee->ext_patch_ieee80211_xmit(skb, dev); ++ goto success; ++ } ++#endif ++ ++ ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); ++#ifdef _RTL8187_EXT_PATCH_ ++ crypt = ieee->cryptlist[0]->crypt[ieee->tx_keyidx]; ++#else ++ crypt = ieee->crypt[ieee->tx_keyidx]; ++#endif ++ encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && ++ ieee->host_encrypt && crypt && crypt->ops; ++ ++ if (!encrypt && ieee->ieee802_1x && ++ ieee->drop_unencrypted && ether_type != ETH_P_PAE) { ++ stats->tx_dropped++; ++ goto success; ++ } ++ ++ #ifdef CONFIG_IEEE80211_DEBUG ++ if (crypt && !encrypt && ether_type == ETH_P_PAE) { ++ struct eapol *eap = (struct eapol *)(skb->data + ++ sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16)); ++ IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", ++ eap_get_type(eap->type)); ++ } ++ #endif ++ ++ /* Save source and destination addresses */ ++ memcpy(&dest, skb->data, ETH_ALEN); ++ memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN); ++ ++ /* Advance the SKB to the start of the payload */ ++ skb_pull(skb, sizeof(struct ethhdr)); ++ ++ /* Determine total amount of storage required for TXB packets */ ++ bytes = skb->len + SNAP_SIZE + sizeof(u16); ++ ++ if(ieee->current_network.QoS_Enable) { ++ if (encrypt) ++ fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA | ++ IEEE80211_FCTL_WEP; ++ else ++ fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA; ++ ++ } else { ++ if (encrypt) ++ fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | ++ IEEE80211_FCTL_WEP; ++ else ++ fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA; ++ } ++ ++ if (ieee->iw_mode == IW_MODE_INFRA) { ++ fc |= IEEE80211_FCTL_TODS; ++ /* To DS: Addr1 = BSSID, Addr2 = SA, ++ Addr3 = DA */ ++ memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN); ++ memcpy(&header.addr2, &src, ETH_ALEN); ++ memcpy(&header.addr3, &dest, ETH_ALEN); ++ } else if (ieee->iw_mode == IW_MODE_ADHOC) { ++ /* not From/To DS: Addr1 = DA, Addr2 = SA, ++ Addr3 = BSSID */ ++ memcpy(&header.addr1, dest, ETH_ALEN); ++ memcpy(&header.addr2, src, ETH_ALEN); ++ memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); ++ } ++ // printk(KERN_WARNING "essid MAC address is "MAC_FMT, MAC_ARG(&header.addr1)); ++ header.frame_ctl = cpu_to_le16(fc); ++ //hdr_len = IEEE80211_3ADDR_LEN; ++ ++ /* Determine fragmentation size based on destination (multicast ++ * and broadcast are not fragmented) */ ++// if (is_multicast_ether_addr(dest) || ++// is_broadcast_ether_addr(dest)) { ++ if (is_multicast_ether_addr(header.addr1) || ++ is_broadcast_ether_addr(header.addr1)) { ++ frag_size = MAX_FRAG_THRESHOLD; ++ QOS_ctl = QOS_CTL_NOTCONTAIN_ACK; ++ } ++ else { ++ //printk(KERN_WARNING "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&frag_size = %d\n", frag_size); ++ frag_size = ieee->fts;//default:392 ++ QOS_ctl = 0; ++ } ++ ++ if (ieee->current_network.QoS_Enable) { ++ hdr_len = IEEE80211_3ADDR_LEN + 2; ++ QOS_ctl |= skb->priority; //set in the ieee80211_classify ++ header.QOS_ctl = cpu_to_le16(QOS_ctl); ++ } else { ++ hdr_len = IEEE80211_3ADDR_LEN; ++ } ++ //printk(KERN_WARNING "header size = %d, QOS_ctl = %x\n", hdr_len,QOS_ctl); ++ /* Determine amount of payload per fragment. Regardless of if ++ * this stack is providing the full 802.11 header, one will ++ * eventually be affixed to this fragment -- so we must account for ++ * it when determining the amount of payload space. */ ++ //bytes_per_frag = frag_size - (IEEE80211_3ADDR_LEN + (ieee->current_network->QoS_Enable ? 2:0)); ++ bytes_per_frag = frag_size - hdr_len; ++ if (ieee->config & ++ (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) ++ bytes_per_frag -= IEEE80211_FCS_LEN; ++ ++ /* Each fragment may need to have room for encryptiong pre/postfix */ ++ if (encrypt) ++ bytes_per_frag -= crypt->ops->extra_prefix_len + ++ crypt->ops->extra_postfix_len; ++ ++ /* Number of fragments is the total bytes_per_frag / ++ * payload_per_fragment */ ++ nr_frags = bytes / bytes_per_frag; ++ bytes_last_frag = bytes % bytes_per_frag; ++ if (bytes_last_frag) ++ nr_frags++; ++ else ++ bytes_last_frag = bytes_per_frag; ++ ++ /* When we allocate the TXB we allocate enough space for the reserve ++ * and full fragment bytes (bytes_per_frag doesn't include prefix, ++ * postfix, header, FCS, etc.) */ ++ txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC); ++ if (unlikely(!txb)) { ++ printk(KERN_WARNING "%s: Could not allocate TXB\n", ++ ieee->dev->name); ++ goto failed; ++ } ++ txb->encrypted = encrypt; ++ txb->payload_size = bytes; ++ ++ for (i = 0; i < nr_frags; i++) { ++ skb_frag = txb->fragments[i]; ++ skb_frag->priority = UP2AC(skb->priority); ++ if (encrypt) ++ skb_reserve(skb_frag, crypt->ops->extra_prefix_len); ++ ++ frag_hdr = (struct ieee80211_hdr_3addr_QOS *)skb_put(skb_frag, hdr_len); ++ memcpy(frag_hdr, &header, hdr_len); ++ ++ /* If this is not the last fragment, then add the MOREFRAGS ++ * bit to the frame control */ ++ if (i != nr_frags - 1) { ++ frag_hdr->frame_ctl = cpu_to_le16( ++ fc | IEEE80211_FCTL_MOREFRAGS); ++ bytes = bytes_per_frag; ++ ++ } else { ++ /* The last fragment takes the remaining length */ ++ bytes = bytes_last_frag; ++ } ++ if(ieee->current_network.QoS_Enable) { ++ // add 1 only indicate to corresponding seq number control 2006/7/12 ++ frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); ++ //printk(KERN_WARNING "skb->priority = %d,", skb->priority); ++ //printk(KERN_WARNING "type:%d: seq = %d\n",UP2AC(skb->priority),ieee->seq_ctrl[UP2AC(skb->priority)+1]); ++ } else { ++ frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); ++ } ++ //frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl<<4 | i); ++ // ++ ++ /* Put a SNAP header on the first fragment */ ++ if (i == 0) { ++ ieee80211_put_snap( ++ skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), ++ ether_type); ++ bytes -= SNAP_SIZE + sizeof(u16); ++ } ++ ++ memcpy(skb_put(skb_frag, bytes), skb->data, bytes); ++ ++ /* Advance the SKB... */ ++ skb_pull(skb, bytes); ++ ++ /* Encryption routine will move the header forward in order ++ * to insert the IV between the header and the payload */ ++ if (encrypt) ++ ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); ++ if (ieee->config & ++ (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) ++ skb_put(skb_frag, 4); ++ } ++ // Advance sequence number in data frame. ++ //printk(KERN_WARNING "QoS Enalbed? %s\n", ieee->current_network.QoS_Enable?"Y":"N"); ++ if (ieee->current_network.QoS_Enable) { ++ if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) ++ ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; ++ else ++ ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; ++ } else { ++ if (ieee->seq_ctrl[0] == 0xFFF) ++ ieee->seq_ctrl[0] = 0; ++ else ++ ieee->seq_ctrl[0]++; ++ } ++ //--- ++ }else{ ++ if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) { ++ printk(KERN_WARNING "%s: skb too small (%d).\n", ++ ieee->dev->name, skb->len); ++ goto success; ++ } ++ ++ txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC); ++ if(!txb){ ++ printk(KERN_WARNING "%s: Could not allocate TXB\n", ++ ieee->dev->name); ++ goto failed; ++ } ++ ++ txb->encrypted = 0; ++ txb->payload_size = skb->len; ++ memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len); ++ } ++ ++ success: ++ spin_unlock_irqrestore(&ieee->lock, flags); ++#ifdef _RTL8187_EXT_PATCH_ ++ // Sometimes, extension mode can reuse skb (by txb->fragments[0]) ++ if( ! ((ieee->iw_mode == ieee->iw_ext_mode) && txb && (txb->fragments[0] == skb)) ) ++#endif ++ dev_kfree_skb_any(skb); ++ if (txb) { ++ if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){ ++ ieee80211_softmac_xmit(txb, ieee); ++ }else{ ++ if ((*ieee->hard_start_xmit)(txb, dev) == 0) { ++ stats->tx_packets++; ++ stats->tx_bytes += txb->payload_size; ++ return 0; ++ } ++ ieee80211_txb_free(txb); ++ } ++ } ++ ++ return 0; ++ ++ failed: ++ spin_unlock_irqrestore(&ieee->lock, flags); ++ netif_stop_queue(dev); ++ printk("netif_stop_queue in ieee80211_xmit \n"); ++ stats->tx_errors++; ++ return 1; ++ ++} ++ ++ ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++EXPORT_SYMBOL(ieee80211_txb_free); ++#ifdef _RTL8187_EXT_PATCH_ ++EXPORT_SYMBOL(ieee80211_alloc_txb); ++EXPORT_SYMBOL(ieee80211_ext_alloc_txb); ++EXPORT_SYMBOL(ieee80211_ext_reuse_txb); ++ ++EXPORT_SYMBOL(ieee80211_encrypt_fragment); ++#endif // _RTL8187_EXT_PATCH_ ++#else ++EXPORT_SYMBOL_NOVERS(ieee80211_txb_free); ++#ifdef _RTL8187_EXT_PATCH_ ++EXPORT_SYMBOL_NOVERS(ieee80211_alloc_txb); ++EXPORT_SYMBOL_NOVERS(ieee80211_ext_reuse_txb); ++ ++EXPORT_SYMBOL_NOVERS(ieee80211_encrypt_fragment); ++#endif // _RTL8187_EXT_PATCH_ ++#endif ++ +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_wx.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_wx.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_wx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/ieee80211_wx.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,926 @@ ++/****************************************************************************** ++ ++ Copyright(c) 2004 Intel Corporation. All rights reserved. ++ ++ Portions of this file are based on the WEP enablement code provided by the ++ Host AP project hostap-drivers v0.1.3 ++ Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen ++ ++ Copyright (c) 2002-2003, Jouni Malinen ++ ++ This program is free software; you can redistribute it and/or modify it ++ under the terms of version 2 of the GNU General Public License as ++ published by the Free Software Foundation. ++ ++ This program is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., 59 ++ Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++ The full GNU General Public License is included in this distribution in the ++ file called LICENSE. ++ ++ Contact Information: ++ James P. Ketrenos ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++******************************************************************************/ ++#include ++#include ++#include ++#include ++ ++#include "ieee80211.h" ++static const char *ieee80211_modes[] = { ++ "?", "a", "b", "ab", "g", "ag", "bg", "abg" ++}; ++ ++#define MAX_CUSTOM_LEN 64 ++static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, ++ char *start, char *stop, ++ struct ieee80211_network *network, ++ struct iw_request_info *info) ++{ ++ char custom[MAX_CUSTOM_LEN]; ++ char *p; ++ struct iw_event iwe; ++ int i, j; ++ u8 max_rate, rate; ++ ++ /* First entry *MUST* be the AP MAC address */ ++ iwe.cmd = SIOCGIWAP; ++ iwe.u.ap_addr.sa_family = ARPHRD_ETHER; ++ memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); ++#else ++ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN); ++#endif ++ /* Remaining entries will be displayed in the order we provide them */ ++ ++ /* Add the ESSID */ ++ iwe.cmd = SIOCGIWESSID; ++ iwe.u.data.flags = 1; ++ //YJ,modified,080903,for hidden ap ++ //if (network->flags & NETWORK_EMPTY_ESSID) { ++ if (network->ssid_len == 0) { ++ iwe.u.data.length = sizeof(""); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_point(info, start, stop, &iwe, ""); ++#else ++ start = iwe_stream_add_point(start, stop, &iwe, ""); ++#endif ++ } else { ++ iwe.u.data.length = min(network->ssid_len, (u8)32); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid); ++#else ++ start = iwe_stream_add_point(start, stop, &iwe, network->ssid); ++#endif ++ } ++ ++ /* Add the protocol name */ ++ iwe.cmd = SIOCGIWNAME; ++ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN); ++#else ++ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_CHAR_LEN); ++#endif ++ /* Add mode */ ++ iwe.cmd = SIOCGIWMODE; ++ if (network->capability & ++ (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) { ++ if (network->capability & WLAN_CAPABILITY_BSS) ++ iwe.u.mode = IW_MODE_MASTER; ++ else ++ iwe.u.mode = IW_MODE_ADHOC; ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_event(info, start, stop, &iwe, ++ IW_EV_UINT_LEN); ++#else ++ start = iwe_stream_add_event(start, stop, &iwe, ++ IW_EV_UINT_LEN); ++#endif ++ } ++ ++ /* Add frequency/channel */ ++ iwe.cmd = SIOCGIWFREQ; ++/* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode); ++ iwe.u.freq.e = 3; */ ++ iwe.u.freq.m = network->channel; ++ iwe.u.freq.e = 0; ++ iwe.u.freq.i = 0; ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); ++#else ++ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN); ++#endif ++ /* Add encryption capability */ ++ iwe.cmd = SIOCGIWENCODE; ++ if (network->capability & WLAN_CAPABILITY_PRIVACY) ++ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; ++ else ++ iwe.u.data.flags = IW_ENCODE_DISABLED; ++ iwe.u.data.length = 0; ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid); ++#else ++ start = iwe_stream_add_point(start, stop, &iwe, network->ssid); ++#endif ++ /* Add basic and extended rates */ ++ max_rate = 0; ++ p = custom; ++ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): "); ++ for (i = 0, j = 0; i < network->rates_len; ) { ++ if (j < network->rates_ex_len && ++ ((network->rates_ex[j] & 0x7F) < ++ (network->rates[i] & 0x7F))) ++ rate = network->rates_ex[j++] & 0x7F; ++ else ++ rate = network->rates[i++] & 0x7F; ++ if (rate > max_rate) ++ max_rate = rate; ++ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), ++ "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); ++ } ++ for (; j < network->rates_ex_len; j++) { ++ rate = network->rates_ex[j] & 0x7F; ++ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), ++ "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); ++ if (rate > max_rate) ++ max_rate = rate; ++ } ++ ++ iwe.cmd = SIOCGIWRATE; ++ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; ++ iwe.u.bitrate.value = max_rate * 500000; ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_event(info, start, stop, &iwe,IW_EV_PARAM_LEN); ++#else ++ start = iwe_stream_add_event(start, stop, &iwe,IW_EV_PARAM_LEN); ++#endif ++ iwe.cmd = IWEVCUSTOM; ++ iwe.u.data.length = p - custom; ++ if (iwe.u.data.length) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_point(info, start, stop, &iwe, custom); ++#else ++ start = iwe_stream_add_point(start, stop, &iwe, custom); ++#endif ++ /* Add quality statistics */ ++ /* TODO: Fix these values... */ ++ iwe.cmd = IWEVQUAL; ++ iwe.u.qual.qual = network->stats.signalstrength;//network->stats.signal; ++ iwe.u.qual.level = network->stats.signal;//network->stats.rssi; ++ iwe.u.qual.noise = network->stats.noise; ++#if 0 ++ iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK; ++ if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) ++ iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID; ++ if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) ++ iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID; ++ if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) ++ iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID; ++#endif ++ ++ iwe.u.qual.updated = 0x7;//network->stats.mask & IEEE80211_STATMASK_WEMASK; ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); ++#else ++ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN); ++#endif ++ iwe.cmd = IWEVCUSTOM; ++ p = custom; ++ ++ iwe.u.data.length = p - custom; ++ if (iwe.u.data.length) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_point(info, start, stop, &iwe, custom); ++#else ++ start = iwe_stream_add_point(start, stop, &iwe, custom); ++#endif ++#if 0 ++ if (ieee->wpa_enabled && network->wpa_ie_len){ ++ char buf[MAX_WPA_IE_LEN * 2 + 30]; ++ // printk("WPA IE\n"); ++ u8 *p = buf; ++ p += sprintf(p, "wpa_ie="); ++ for (i = 0; i < network->wpa_ie_len; i++) { ++ p += sprintf(p, "%02x", network->wpa_ie[i]); ++ } ++ ++ memset(&iwe, 0, sizeof(iwe)); ++ iwe.cmd = IWEVCUSTOM; ++ iwe.u.data.length = strlen(buf); ++ start = iwe_stream_add_point(start, stop, &iwe, buf); ++ } ++ ++ if (ieee->wpa_enabled && network->rsn_ie_len){ ++ char buf[MAX_WPA_IE_LEN * 2 + 30]; ++ ++ u8 *p = buf; ++ p += sprintf(p, "rsn_ie="); ++ for (i = 0; i < network->rsn_ie_len; i++) { ++ p += sprintf(p, "%02x", network->rsn_ie[i]); ++ } ++ ++ ++#else ++ memset(&iwe, 0, sizeof(iwe)); ++ if (network->wpa_ie_len) { ++ //printk("wpa_ie_len:%d\n", network->wpa_ie_len); ++ char buf[MAX_WPA_IE_LEN]; ++ memcpy(buf, network->wpa_ie, network->wpa_ie_len); ++ iwe.cmd = IWEVGENIE; ++ iwe.u.data.length = network->wpa_ie_len; ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_point(info, start, stop, &iwe, buf); ++#else ++ start = iwe_stream_add_point(start, stop, &iwe, buf); ++#endif ++ } ++ ++ memset(&iwe, 0, sizeof(iwe)); ++ if (network->rsn_ie_len) { ++ //printk("=====>rsn_ie_len:\n", network->rsn_ie_len); ++ #if 0 ++ { ++ int i; ++ for (i=0; irsn_ie_len; i++); ++ printk("%2x ", network->rsn_ie[i]); ++ printk("\n"); ++ } ++ #endif ++ char buf[MAX_WPA_IE_LEN]; ++ memcpy(buf, network->rsn_ie, network->rsn_ie_len); ++ iwe.cmd = IWEVGENIE; ++ iwe.u.data.length = network->rsn_ie_len; ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_point(info, start, stop, &iwe, buf); ++#else ++ start = iwe_stream_add_point(start, stop, &iwe, buf); ++#endif ++ } ++ ++#endif ++ ++ /* Add EXTRA: Age to display seconds since last beacon/probe response ++ * for given network. */ ++ iwe.cmd = IWEVCUSTOM; ++ p = custom; ++ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), ++ " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100)); ++ iwe.u.data.length = p - custom; ++ if (iwe.u.data.length) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) || defined (QMI_26_6)) ++ start = iwe_stream_add_point(info, start, stop, &iwe, custom); ++#else ++ start = iwe_stream_add_point(start, stop, &iwe, custom); ++#endif ++ ++ return start; ++} ++ ++int ieee80211_wx_get_scan(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct ieee80211_network *network; ++ unsigned long flags; ++ int err = 0; ++ char *ev = extra; ++ char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA; ++ //char *stop = ev + IW_SCAN_MAX_DATA; ++ int i = 0; ++ ++ IEEE80211_DEBUG_WX("Getting scan\n"); ++ down(&ieee->wx_sem); ++ spin_lock_irqsave(&ieee->lock, flags); ++ ++ if(!ieee->bHwRadioOff) ++ { ++ list_for_each_entry(network, &ieee->network_list, list) { ++ i++; ++ ++ if((stop-ev)<200) ++ { ++ err = -E2BIG; ++ break; ++ } ++ ++ if (ieee->scan_age == 0 || ++ time_after(network->last_scanned + ieee->scan_age, jiffies)) ++ { ++ ev = rtl819x_translate_scan(ieee, ev, stop, network, info); ++ } ++ else ++ IEEE80211_DEBUG_SCAN( ++ "Not showing network '%s (" ++ MAC_FMT ")' due to age (%lums).\n", ++ escape_essid(network->ssid, ++ network->ssid_len), ++ MAC_ARG(network->bssid), ++ (jiffies - network->last_scanned) / (HZ / 100)); ++ } ++ } ++ spin_unlock_irqrestore(&ieee->lock, flags); ++ up(&ieee->wx_sem); ++ wrqu->data.length = ev - extra; ++ wrqu->data.flags = 0; ++ ++ IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i); ++ ++ return err; ++} ++ ++int ieee80211_wx_set_encode(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *keybuf) ++{ ++ struct iw_point *erq = &(wrqu->encoding); ++ struct net_device *dev = ieee->dev; ++ struct ieee80211_security sec = { ++ .flags = 0 ++ }; ++ int i, key, key_provided, len; ++ struct ieee80211_crypt_data **crypt; ++ ++ IEEE80211_DEBUG_WX("SET_ENCODE\n"); ++ ++ key = erq->flags & IW_ENCODE_INDEX; ++ if (key) { ++ if (key > WEP_KEYS) ++ return -EINVAL; ++ key--; ++ key_provided = 1; ++ } else { ++ key_provided = 0; ++ key = ieee->tx_keyidx; ++ } ++ ++ IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ? ++ "provided" : "default"); ++#ifdef _RTL8187_EXT_PATCH_ ++#if 0 ++{ ++ int j; ++ for(j=0; jcryptlist[j]->crypt[key]; ++#else ++ crypt = &ieee->cryptlist[0]->crypt[key]; ++#endif ++#else ++ crypt = &ieee->crypt[key]; ++#endif ++ if (erq->flags & IW_ENCODE_DISABLED) { ++ if (key_provided && *crypt) { ++ IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n", ++ key); ++ ieee80211_crypt_delayed_deinit(ieee, crypt); ++ } else ++ IEEE80211_DEBUG_WX("Disabling encryption.\n"); ++ ++ /* Check all the keys to see if any are still configured, ++ * and if no key index was provided, de-init them all */ ++ for (i = 0; i < WEP_KEYS; i++) { ++#ifdef _RTL8187_EXT_PATCH_ ++ ++ if (ieee->cryptlist[0]->crypt[i] != NULL){ ++#else ++ ++ if (ieee->crypt[i] != NULL) { ++#endif ++ if (key_provided) ++ break; ++ ieee80211_crypt_delayed_deinit( ++#ifdef _RTL8187_EXT_PATCH_ ++ ieee, &ieee->cryptlist[0]->crypt[i]); ++#else ++ ieee, &ieee->crypt[i]); ++#endif ++ } ++ } ++ ++ if (i == WEP_KEYS) { ++ sec.enabled = 0; ++ sec.level = SEC_LEVEL_0; ++ sec.flags |= SEC_ENABLED | SEC_LEVEL; ++ } ++ ++ goto done; ++ } ++ ++ ++ ++ sec.enabled = 1; ++ sec.flags |= SEC_ENABLED; ++ ++ if (*crypt != NULL && (*crypt)->ops != NULL && ++ strcmp((*crypt)->ops->name, "WEP") != 0) { ++ /* changing to use WEP; deinit previously used algorithm ++ * on this key */ ++ ieee80211_crypt_delayed_deinit(ieee, crypt); ++ } ++ ++ if (*crypt == NULL) { ++ struct ieee80211_crypt_data *new_crypt; ++ ++ /* take WEP into use */ ++ new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data), ++ GFP_KERNEL); ++ if (new_crypt == NULL) ++ return -ENOMEM; ++ memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); ++ new_crypt->ops = ieee80211_get_crypto_ops("WEP"); ++ if (!new_crypt->ops) { ++ request_module("ieee80211_crypt_wep"); ++ new_crypt->ops = ieee80211_get_crypto_ops("WEP"); ++ } ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ++ if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) ++#else ++ if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner)) ++#endif ++ new_crypt->priv = new_crypt->ops->init(key); ++ ++ if (!new_crypt->ops || !new_crypt->priv) { ++ kfree(new_crypt); ++ new_crypt = NULL; ++ ++ printk(KERN_WARNING "%s: could not initialize WEP: " ++ "load module ieee80211_crypt_wep\n", ++ dev->name); ++ return -EOPNOTSUPP; ++ } ++ *crypt = new_crypt; ++ } ++ ++ /* If a new key was provided, set it up */ ++ if (erq->length > 0) { ++ len = erq->length <= 5 ? 5 : 13; ++ memcpy(sec.keys[key], keybuf, erq->length); ++ if (len > erq->length) ++ memset(sec.keys[key] + erq->length, 0, ++ len - erq->length); ++ IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n", ++ key, escape_essid(sec.keys[key], len), ++ erq->length, len); ++ sec.key_sizes[key] = len; ++ (*crypt)->ops->set_key(sec.keys[key], len, NULL, ++ (*crypt)->priv); ++ sec.flags |= (1 << key); ++ /* This ensures a key will be activated if no key is ++ * explicitely set */ ++ if (key == sec.active_key) ++ sec.flags |= SEC_ACTIVE_KEY; ++ ++ ieee->tx_keyidx = key; //we need it to support multi_key setting. added by wb 2008_2_22 ++ } else { ++ len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN, ++ NULL, (*crypt)->priv); ++ if (len == 0) { ++ /* Set a default key of all 0 */ ++ IEEE80211_DEBUG_WX("Setting key %d to all zero.\n", ++ key); ++ memset(sec.keys[key], 0, 13); ++ (*crypt)->ops->set_key(sec.keys[key], 13, NULL, ++ (*crypt)->priv); ++ sec.key_sizes[key] = 13; ++ sec.flags |= (1 << key); ++ } ++ ++ /* No key data - just set the default TX key index */ ++ if (key_provided) { ++ IEEE80211_DEBUG_WX( ++ "Setting key %d to default Tx key.\n", key); ++ ieee->tx_keyidx = key; ++ sec.active_key = key; ++ sec.flags |= SEC_ACTIVE_KEY; ++ } ++ } ++#ifdef _RTL8187_EXT_PATCH_ ++#if 0 ++} ++} ++#endif ++#endif ++ done: ++ ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED); ++ sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; ++ sec.flags |= SEC_AUTH_MODE; ++ IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ? ++ "OPEN" : "SHARED KEY"); ++ ++ /* For now we just support WEP, so only set that security level... ++ * TODO: When WPA is added this is one place that needs to change */ ++ sec.flags |= SEC_LEVEL; ++ sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */ ++ ++ if (ieee->set_security) ++ ieee->set_security(dev, &sec); ++ ++ /* Do not reset port if card is in Managed mode since resetting will ++ * generate new IEEE 802.11 authentication which may end up in looping ++ * with IEEE 802.1X. If your hardware requires a reset after WEP ++ * configuration (for example... Prism2), implement the reset_port in ++ * the callbacks structures used to initialize the 802.11 stack. */ ++ if (ieee->reset_on_keychange && ++ ieee->iw_mode != IW_MODE_INFRA && ++ ieee->reset_port && ieee->reset_port(dev)) { ++ printk(KERN_DEBUG "%s: reset_port failed\n", dev->name); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++int ieee80211_wx_get_encode(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *keybuf) ++{ ++ struct iw_point *erq = &(wrqu->encoding); ++ int len, key; ++ struct ieee80211_crypt_data *crypt; ++ ++ IEEE80211_DEBUG_WX("GET_ENCODE\n"); ++ ++ if(ieee->iw_mode == IW_MODE_MONITOR) ++ return -1; ++ ++ key = erq->flags & IW_ENCODE_INDEX; ++ if (key) { ++ if (key > WEP_KEYS) ++ return -EINVAL; ++ key--; ++ } else ++ key = ieee->tx_keyidx; ++#ifdef _RTL8187_EXT_PATCH_ ++ crypt = ieee->cryptlist[0]->crypt[key]; ++#else ++ crypt = ieee->crypt[key]; ++#endif ++ erq->flags = key + 1; ++ ++ if (crypt == NULL || crypt->ops == NULL) { ++ erq->length = 0; ++ erq->flags |= IW_ENCODE_DISABLED; ++ return 0; ++ } ++ ++ if (strcmp(crypt->ops->name, "WEP") != 0) { ++ /* only WEP is supported with wireless extensions, so just ++ * report that encryption is used */ ++ erq->length = 0; ++ erq->flags |= IW_ENCODE_ENABLED; ++ return 0; ++ } ++ ++ len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv); ++ erq->length = (len >= 0 ? len : 0); ++ ++ erq->flags |= IW_ENCODE_ENABLED; ++ ++ if (ieee->open_wep) ++ erq->flags |= IW_ENCODE_OPEN; ++ else ++ erq->flags |= IW_ENCODE_RESTRICTED; ++ ++ return 0; ++} ++ ++int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct net_device *dev = ieee->dev; ++ struct iw_point *encoding = &wrqu->encoding; ++ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; ++ int i, idx, ret = 0; ++ int group_key = 0; ++ const char *alg, *module; ++ struct ieee80211_crypto_ops *ops; ++ struct ieee80211_crypt_data **crypt; ++ ++ struct ieee80211_security sec = { ++ .flags = 0, ++ }; ++ //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg); ++ idx = encoding->flags & IW_ENCODE_INDEX; ++ if (idx) { ++ if (idx < 1 || idx > WEP_KEYS) ++ return -EINVAL; ++ idx--; ++ } else ++ idx = ieee->tx_keyidx; ++ ++ if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { ++#ifdef _RTL8187_EXT_PATCH_ ++ crypt = &ieee->cryptlist[0]->crypt[idx]; ++#else ++ crypt = &ieee->crypt[idx]; ++#endif ++ group_key = 1; ++ } else { ++ /* some Cisco APs use idx>0 for unicast in dynamic WEP */ ++ //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg); ++ if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP) ++ return -EINVAL; ++ if (ieee->iw_mode == IW_MODE_INFRA) ++#ifdef _RTL8187_EXT_PATCH_ ++ crypt = &ieee->cryptlist[0]->crypt[idx]; ++#else ++ crypt = &ieee->crypt[idx]; ++#endif ++ else ++ return -EINVAL; ++ } ++ ++ sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT; ++ if ((encoding->flags & IW_ENCODE_DISABLED) || ++ ext->alg == IW_ENCODE_ALG_NONE) { ++ if (*crypt) ++ ieee80211_crypt_delayed_deinit(ieee, crypt); ++ ++ for (i = 0; i < WEP_KEYS; i++) ++#ifdef _RTL8187_EXT_PATCH_ ++ if (ieee->cryptlist[0]->crypt[i] != NULL) ++#else ++ if (ieee->crypt[i] != NULL) ++#endif ++ break; ++ ++ if (i == WEP_KEYS) { ++ sec.enabled = 0; ++ // sec.encrypt = 0; ++ sec.level = SEC_LEVEL_0; ++ sec.flags |= SEC_LEVEL; ++ } ++ //printk("disabled: flag:%x\n", encoding->flags); ++ goto done; ++ } ++ ++ sec.enabled = 1; ++ // sec.encrypt = 1; ++#if 0 ++ if (group_key ? !ieee->host_mc_decrypt : ++ !(ieee->host_encrypt || ieee->host_decrypt || ++ ieee->host_encrypt_msdu)) ++ goto skip_host_crypt; ++#endif ++ switch (ext->alg) { ++ case IW_ENCODE_ALG_WEP: ++ alg = "WEP"; ++ module = "ieee80211_crypt_wep"; ++ break; ++ case IW_ENCODE_ALG_TKIP: ++ alg = "TKIP"; ++ module = "ieee80211_crypt_tkip"; ++ break; ++ case IW_ENCODE_ALG_CCMP: ++ alg = "CCMP"; ++ module = "ieee80211_crypt_ccmp"; ++ break; ++ default: ++ IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", ++ dev->name, ext->alg); ++ ret = -EINVAL; ++ goto done; ++ } ++ printk("alg name:%s\n",alg); ++ ++ ops = ieee80211_get_crypto_ops(alg); ++ if (ops == NULL) { ++ request_module(module); ++ ops = ieee80211_get_crypto_ops(alg); ++ } ++ if (ops == NULL) { ++ IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", ++ dev->name, ext->alg); ++ printk("========>unknown crypto alg %d\n", ext->alg); ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ if (*crypt == NULL || (*crypt)->ops != ops) { ++ struct ieee80211_crypt_data *new_crypt; ++ ++ ieee80211_crypt_delayed_deinit(ieee, crypt); ++ ++ new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL); ++ if (new_crypt == NULL) { ++ ret = -ENOMEM; ++ goto done; ++ } ++ new_crypt->ops = ops; ++ if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) ++ new_crypt->priv = new_crypt->ops->init(idx); ++ if (new_crypt->priv == NULL) { ++ kfree(new_crypt); ++ ret = -EINVAL; ++ goto done; ++ } ++ *crypt = new_crypt; ++ ++ } ++ //I need to deinit other crypt here in mesh mode instead deinit them while use them to tx&rx. ++#ifdef _RTL8187_EXT_PATCH_ ++ if (ieee->iw_mode == ieee->iw_ext_mode) ++ { ++ int j; ++ for (j=1; jcryptlist[j]->crypt[idx]; ++ if (*crypttmp == NULL) ++ break; ++ if (*crypttmp && (*crypttmp)->ops != ops) ++ ieee80211_crypt_delayed_deinit(ieee, crypttmp); ++ } ++ } ++#endif ++ if (ext->key_len > 0 && (*crypt)->ops->set_key && ++ (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq, ++ (*crypt)->priv) < 0) { ++ IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name); ++ printk("key setting failed\n"); ++ ret = -EINVAL; ++ goto done; ++ } ++#if 1 ++// skip_host_crypt: ++ //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags); ++ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { ++ ieee->tx_keyidx = idx; ++ sec.active_key = idx; ++ sec.flags |= SEC_ACTIVE_KEY; ++ } ++ ++ if (ext->alg != IW_ENCODE_ALG_NONE) { ++ memcpy(sec.keys[idx], ext->key, ext->key_len); ++ sec.key_sizes[idx] = ext->key_len; ++ sec.flags |= (1 << idx); ++ if (ext->alg == IW_ENCODE_ALG_WEP) { ++ // sec.encode_alg[idx] = SEC_ALG_WEP; ++ sec.flags |= SEC_LEVEL; ++ sec.level = SEC_LEVEL_1; ++ } else if (ext->alg == IW_ENCODE_ALG_TKIP) { ++ // sec.encode_alg[idx] = SEC_ALG_TKIP; ++ sec.flags |= SEC_LEVEL; ++ sec.level = SEC_LEVEL_2; ++ } else if (ext->alg == IW_ENCODE_ALG_CCMP) { ++ // sec.encode_alg[idx] = SEC_ALG_CCMP; ++ sec.flags |= SEC_LEVEL; ++ sec.level = SEC_LEVEL_3; ++ } ++ /* Don't set sec level for group keys. */ ++ if (group_key) ++ sec.flags &= ~SEC_LEVEL; ++ } ++#endif ++done: ++ if (ieee->set_security) ++ ieee->set_security(ieee->dev, &sec); ++ ++ if (ieee->reset_on_keychange && ++ ieee->iw_mode != IW_MODE_INFRA && ++ ieee->reset_port && ieee->reset_port(dev)) { ++ IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name); ++ return -EINVAL; ++ } ++ ++ return ret; ++} ++int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct iw_mlme *mlme = (struct iw_mlme *) extra; ++// printk("\ndkgadfslkdjgalskdf===============>%s(), cmd:%x\n", __FUNCTION__, mlme->cmd); ++#if 1 ++ switch (mlme->cmd) { ++ case IW_MLME_DEAUTH: ++ case IW_MLME_DISASSOC: ++ // printk("disassoc now\n"); ++ ieee80211_disassociate(ieee); ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++#endif ++ return 0; ++} ++ ++int ieee80211_wx_set_auth(struct ieee80211_device *ieee, ++ struct iw_request_info *info, ++ struct iw_param *data, char *extra) ++{ ++/* ++ struct ieee80211_security sec = { ++ .flags = SEC_AUTH_MODE, ++ } ++*/ ++ //printk("set auth:flag:%x, data value:%x\n", data->flags, data->value); ++ switch (data->flags & IW_AUTH_INDEX) { ++ case IW_AUTH_WPA_VERSION: ++ /*need to support wpa2 here*/ ++ //printk("wpa version:%x\n", data->value); ++ break; ++ case IW_AUTH_CIPHER_PAIRWISE: ++ case IW_AUTH_CIPHER_GROUP: ++ case IW_AUTH_KEY_MGMT: ++ /* ++ * * Host AP driver does not use these parameters and allows ++ * * wpa_supplicant to control them internally. ++ * */ ++ break; ++ case IW_AUTH_TKIP_COUNTERMEASURES: ++ ieee->tkip_countermeasures = data->value; ++ break; ++ case IW_AUTH_DROP_UNENCRYPTED: ++ ieee->drop_unencrypted = data->value; ++ break; ++ ++ case IW_AUTH_80211_AUTH_ALG: ++ ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0; ++ //printk("open_wep:%d\n", ieee->open_wep); ++ break; ++ ++#if 1 ++ case IW_AUTH_WPA_ENABLED: ++ ieee->wpa_enabled = (data->value)?1:0; ++ //printk("enalbe wpa:%d\n", ieee->wpa_enabled); ++ break; ++ ++#endif ++ case IW_AUTH_RX_UNENCRYPTED_EAPOL: ++ ieee->ieee802_1x = data->value; ++ break; ++ case IW_AUTH_PRIVACY_INVOKED: ++ ieee->privacy_invoked = data->value; ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ return 0; ++} ++ ++#if 1 ++int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len) ++{ ++#if 0 ++ printk("====>%s()\n", __FUNCTION__); ++ { ++ int i; ++ for (i=0; iMAX_WPA_IE_LEN || (len && ie == NULL)) ++ { ++ // printk("return error out, len:%d\n", len); ++ return -EINVAL; ++ } ++ if (len) ++ { ++ ++ if (len != ie[1]+2) printk("len:%d, ie:%d\n", (int)len, ie[1]); ++ buf = kmalloc(len, GFP_KERNEL); ++ if (buf == NULL) ++ return -ENOMEM; ++ memcpy(buf, ie, len); ++ kfree(ieee->wpa_ie); ++ ieee->wpa_ie = buf; ++ ieee->wpa_ie_len = len; ++ } ++ else{ ++ if (ieee->wpa_ie) ++ kfree(ieee->wpa_ie); ++ ieee->wpa_ie = NULL; ++ ieee->wpa_ie_len = 0; ++ } ++// printk("<=====out %s()\n", __FUNCTION__); ++ ++ return 0; ++ ++} ++#endif ++ ++EXPORT_SYMBOL(ieee80211_wx_set_gen_ie); ++EXPORT_SYMBOL(ieee80211_wx_set_mlme); ++EXPORT_SYMBOL(ieee80211_wx_set_auth); ++EXPORT_SYMBOL(ieee80211_wx_set_encode_ext); ++EXPORT_SYMBOL(ieee80211_wx_get_scan); ++EXPORT_SYMBOL(ieee80211_wx_set_encode); ++EXPORT_SYMBOL(ieee80211_wx_get_encode); ++#if 0 ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_scan); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_encode); ++EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_encode); ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/internal.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/internal.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/internal.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/internal.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,115 @@ ++/* ++ * Cryptographic API. ++ * ++ * Copyright (c) 2002 James Morris ++ * ++ * 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. ++ * ++ */ ++#ifndef _CRYPTO_INTERNAL_H ++#define _CRYPTO_INTERNAL_H ++ ++ ++//#include ++#include "rtl_crypto.h" ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20)) ++#define list_for_each_entry(pos, head, member) \ ++ for (pos = list_entry((head)->next, typeof(*pos), member), \ ++ prefetch(pos->member.next); \ ++ &pos->member != (head); \ ++ pos = list_entry(pos->member.next, typeof(*pos), member), \ ++ prefetch(pos->member.next)) ++ ++static inline void cond_resched(void) ++{ ++ if (need_resched()) { ++ set_current_state(TASK_RUNNING); ++ schedule(); ++ } ++} ++#endif ++ ++extern enum km_type crypto_km_types[]; ++ ++static inline enum km_type crypto_kmap_type(int out) ++{ ++ return crypto_km_types[(in_softirq() ? 2 : 0) + out]; ++} ++ ++static inline void *crypto_kmap(struct page *page, int out) ++{ ++ return kmap_atomic(page, crypto_kmap_type(out)); ++} ++ ++static inline void crypto_kunmap(void *vaddr, int out) ++{ ++ kunmap_atomic(vaddr, crypto_kmap_type(out)); ++} ++ ++static inline void crypto_yield(struct crypto_tfm *tfm) ++{ ++ if (!in_softirq()) ++ cond_resched(); ++} ++ ++static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) ++{ ++ return (void *)&tfm[1]; ++} ++ ++struct crypto_alg *crypto_alg_lookup(const char *name); ++ ++#ifdef CONFIG_KMOD ++void crypto_alg_autoload(const char *name); ++struct crypto_alg *crypto_alg_mod_lookup(const char *name); ++#else ++static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name) ++{ ++ return crypto_alg_lookup(name); ++} ++#endif ++ ++#ifdef CONFIG_CRYPTO_HMAC ++int crypto_alloc_hmac_block(struct crypto_tfm *tfm); ++void crypto_free_hmac_block(struct crypto_tfm *tfm); ++#else ++static inline int crypto_alloc_hmac_block(struct crypto_tfm *tfm) ++{ ++ return 0; ++} ++ ++static inline void crypto_free_hmac_block(struct crypto_tfm *tfm) ++{ } ++#endif ++ ++#ifdef CONFIG_PROC_FS ++void __init crypto_init_proc(void); ++#else ++static inline void crypto_init_proc(void) ++{ } ++#endif ++ ++int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags); ++int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags); ++int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags); ++ ++int crypto_init_digest_ops(struct crypto_tfm *tfm); ++int crypto_init_cipher_ops(struct crypto_tfm *tfm); ++int crypto_init_compress_ops(struct crypto_tfm *tfm); ++ ++void crypto_exit_digest_ops(struct crypto_tfm *tfm); ++void crypto_exit_cipher_ops(struct crypto_tfm *tfm); ++void crypto_exit_compress_ops(struct crypto_tfm *tfm); ++ ++#endif /* _CRYPTO_INTERNAL_H */ ++ +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/kmap_types.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/kmap_types.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/kmap_types.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/kmap_types.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,20 @@ ++#ifndef __KMAP_TYPES_H ++ ++#define __KMAP_TYPES_H ++ ++ ++enum km_type { ++ KM_BOUNCE_READ, ++ KM_SKB_SUNRPC_DATA, ++ KM_SKB_DATA_SOFTIRQ, ++ KM_USER0, ++ KM_USER1, ++ KM_BH_IRQ, ++ KM_SOFTIRQ0, ++ KM_SOFTIRQ1, ++ KM_TYPE_NR ++}; ++ ++#define _ASM_KMAP_TYPES_H ++ ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/readme linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/readme +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/readme 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/readme 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,162 @@ ++What this layer should do ++ ++- It mantain the old mechanism as alternative, so the ++ ipw2100 driver works with really few changes. ++- Encapsulate / Decapsulate ieee80211 packet ++- Handle fragmentation ++- Optionally provide an alterantive mechanism for netif queue stop/wake, ++ so that the ieee80211 layer will pass one fragment per time instead of ++ one txb struct per time. so the driver can stop the queue in the middle ++ of a packet. ++- Provide two different TX interfaces for cards that can handle management ++ frames on one HW queue, and data on another, and for cards that have only ++ one HW queue (the latter untested and very, very rough). ++- Optionally provide the logic for handling IBSS/MASTER/MONITOR/BSS modes ++ and for the channel, essid and wap get/set wireless extension requests. ++ so that the driver has only to change channel when the ieee stack tell it. ++- Optionally provide a scanning mechanism so that the driver has not to ++ worry about this, just implement the set channel calback and pass ++ frames to the upper layer ++- Optionally provide the bss client protocol handshaking (just with open ++ authentication) ++- Optionally provide the probe request send mechanism ++- Optionally provide the bss master mode logic to handle association ++ protocol (only open authentication) and probe responses. ++- SW wep encryption (with open authentication) ++- It collects some stats ++- It provides beacons to the card when it ask for them ++ ++What this layer doesn't do (yet) ++- Perform shared authentication ++- Have full support for master mode (the AP should loop back in the air ++ frames from an associated client to another. This could be done easily ++ with few lines of code, and it is done in my previous version of the ++ stach, but a table of association must be keept and a disassociation ++ policy must be decided and implemented. ++- Handle cleanly the full ieee 802.11 protocol. In AP mode it never ++ disassociate clients, and it is really prone to always allow access. ++ In bss client mode it is a bit rough with AP deauth and disassoc requests. ++- It has not any entry point to view the collected stats. ++- Altought it takes care of the card supported rates in the management frame ++ it sends, support for rate changing on TXed packet is not complete. ++- Give up once associated in bss client mode (it never detect a ++ signal loss condition to disassociate and restart scanning) ++- Provide a mechanism for enabling the TX in monitor mode, so ++ userspace programs can TX raw packets. ++- Provide a mechanism for cards that need that the SW take care of beacon ++ TX completely, in sense that the SW has to enqueue by itself beacons ++ to the card so it TX them (if any...) ++APIs ++ ++Callback functions in the original stack has been mantained. ++following has been added (from ieee80211.h) ++ ++ /* Softmac-generated frames (mamagement) are TXed via this ++ * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is ++ * not set. As some cards may have different HW queues that ++ * one might want to use for data and management frames ++ * the option to have two callbacks might be useful. ++ * This fucntion can't sleep. ++ */ ++ int (*softmac_hard_start_xmit)(struct sk_buff *skb, ++ struct net_device *dev); ++ ++ /* used instead of hard_start_xmit (not softmac_hard_start_xmit) ++ * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data ++ * frames. I the option IEEE_SOFTMAC_SINGLE_QUEUE is also set ++ * then also management frames are sent via this callback. ++ * This function can't sleep. ++ */ ++ void (*softmac_data_hard_start_xmit)(struct sk_buff *skb, ++ struct net_device *dev); ++ ++ /* stops the HW queue for DATA frames. Useful to avoid ++ * waste time to TX data frame when we are reassociating ++ * This function can sleep. ++ */ ++ void (*data_hard_stop)(struct net_device *dev); ++ ++ /* OK this is complementar to data_poll_hard_stop */ ++ void (*data_hard_resume)(struct net_device *dev); ++ ++ /* ask to the driver to retune the radio . ++ * This function can sleep. the driver should ensure ++ * the radio has been swithced before return. ++ */ ++ void (*set_chan)(struct net_device *dev,short ch); ++ ++ /* These are not used if the ieee stack takes care of ++ * scanning (IEEE_SOFTMAC_SCAN feature set). ++ * In this case only the set_chan is used. ++ * ++ * The syncro version is similar to the start_scan but ++ * does not return until all channels has been scanned. ++ * this is called in user context and should sleep, ++ * it is called in a work_queue when swithcing to ad-hoc mode ++ * or in behalf of iwlist scan when the card is associated ++ * and root user ask for a scan. ++ * the fucntion stop_scan should stop both the syncro and ++ * background scanning and can sleep. ++ * The fucntion start_scan should initiate the background ++ * scanning and can't sleep. ++ */ ++ void (*scan_syncro)(struct net_device *dev); ++ void (*start_scan)(struct net_device *dev); ++ void (*stop_scan)(struct net_device *dev); ++ ++ /* indicate the driver that the link state is changed ++ * for example it may indicate the card is associated now. ++ * Driver might be interested in this to apply RX filter ++ * rules or simply light the LINK led ++ */ ++ void (*link_change)(struct net_device *dev); ++ ++Functions hard_data_[resume/stop] are optional and should not be used ++if the driver decides to uses data+management frames enqueue in a ++single HQ queue (thus using just the softmac_hard_data_start_xmit ++callback). ++ ++Function that the driver can use are: ++ ++ieee80211_get_beacon - this is called by the driver when ++ the HW needs a beacon. ++ieee80211_softmac_start_protocol - this should normally be called in the ++ driver open function ++ieee80211_softmac_stop_protocol - the opposite of the above ++ieee80211_wake_queue - this is similar to netif_wake_queue ++ieee80211_reset_queue - this throw away fragments pending(if any) ++ieee80211_stop_queue - this is similar to netif_stop_queue ++ ++ ++known BUGS: ++- When performing syncro scan (possiblily when swithcing to ad-hoc mode ++ and when running iwlist scan when associated) there is still an odd ++ behaviour.. I have not looked in this more accurately (yet). ++ ++locking: ++locking is done by means of three structures. ++1- ieee->lock (by means of spin_[un]lock_irq[save/restore] ++2- ieee->wx_sem ++3- ieee->scan_sem ++ ++the lock 1 is what protect most of the critical sections in the ieee stack. ++the lock 2 is used to avoid that more than one of the SET wireless extension ++handlers (as well as start/stop protocol function) are running at the same time. ++the lock 1 is used when we need to modify or read the shared data in the wx handlers. ++In other words the lock 2 will prevent one SET action will run across another SET ++action (by make sleep the 2nd one) but allow GET actions, while the lock 1 ++make atomic those little shared data access in both GET and SET operation. ++So get operation will be never be delayed really: they will never sleep.. ++Furthermore in the top of some SET operations a flag is set before acquiring ++the lock. This is an help to make the previous running SET operation to ++finish faster if needed (just in case the second one will totally undo the ++first, so there is not need to complete the 1st really.. ). ++The background scanning mechaninsm is protected by the lock 1 except for the ++workqueue. this wq is here just to let the set_chan callback sleep (I thinked it ++might be appreciated by USB network card driver developer). In this case the lock 3 ++take its turn. ++Thus the stop function needs both the locks. ++Funny in the syncro scan the lock 2 play its role (as both the syncro_scan ++function and the stop scan function are called with this semaphore held). ++ ++ +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/rtl8187_mesh.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/rtl8187_mesh.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/rtl8187_mesh.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/rtl8187_mesh.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,282 @@ ++#ifndef _RTL8187_MESH_H_ ++#define _RTL8187_MESH_H_ ++ ++#include "msh_class.h" // struct mshclass ++#include "mesh.h" // struct MESH-Neighbor-Entry ++#include "ieee80211.h" // struct ieee80211-network ++#include "mesh_8185_util.h" // DOT11-QUEUE ++#include "hash_table.h" // hash-table ++#include "8185s_pathsel.h" ++#include ++ ++#define GET_MESH_PRIV(x) ((struct mshclass_priv *)(x->priv)) ++ ++struct ieee80211_hdr_mesh { ++ u16 frame_ctl; ++ u16 duration_id; ++ u8 addr1[ETH_ALEN]; ++ u8 addr2[ETH_ALEN]; ++ u8 addr3[ETH_ALEN]; ++ u16 seq_ctl; ++ u8 addr4[ETH_ALEN]; ++ unsigned char mesh_flag; ++ INT8 TTL; ++ UINT16 segNum; ++ unsigned char DestMACAddr[ETH_ALEN]; // modify for 6 address ++ unsigned char SrcMACAddr[ETH_ALEN]; ++} __attribute__ ((packed)); ++ ++struct myMeshIDNode { ++ struct list_head list; ++ char id[MESH_ID_LEN+1]; ++ short popEN; ++ char tried; ++ unsigned long expire; ++ struct ieee80211_network mesh_network; ++}; ++ ++struct ieee80211_hdr_mesh_QOS { ++ u16 frame_ctl; ++ u16 duration_id; ++ u8 addr1[ETH_ALEN]; ++ u8 addr2[ETH_ALEN]; ++ u8 addr3[ETH_ALEN]; ++ u16 seq_ctl; ++ u8 addr4[ETH_ALEN]; ++ u16 QOS_ctl; ++ unsigned char mesh_flag; ++ INT8 TTL; ++ UINT16 segNum; ++ unsigned char DestMACAddr[ETH_ALEN]; // modify for 6 address ++ unsigned char SrcMACAddr[ETH_ALEN]; ++} __attribute__ ((packed)); ++ ++ ++struct mesh_PeerEntry { ++ // based on 8185ag.h ++ struct list_head hash_list; ++ unsigned int used; ///< used == TRUE => has been allocated, \n used == FALSE => can be allocated ++ unsigned char hwaddr[MACADDRLEN]; ///< hardware address ++ ++ // struct list_head mesh_unEstablish_ptr; // ©|¥¼(©Î±q¤w³s½u -> ¥¼³s½u) ¤§ MP list ++ struct list_head mesh_mp_ptr; // MP list ++ ++ /*mesh_neighbor: ++ * Inited by "Neighbor Discovering" ++ * cleaned by "Disassociation" or "Expired" ++ */ ++ struct MESH_Neighbor_Entry mesh_neighbor_TBL; ++ ++ struct ieee80211_network * pstat; // a backward pointer ++ ++ // 802.11 seq checking ++ u16 last_rxseq; /* rx seq previous per-tid */ ++ u16 last_rxfrag;/* tx frag previous per-tid */ ++ unsigned long last_time; ++ // ++}; ++ ++ ++struct mshclass_priv { ++ ++ struct mesh_PeerEntry *meshEntries; // 1-to-1 for priv->ieee80211->networks ++ ++ spinlock_t lock_stainfo; // lock for accessing the data structure of stat info ++ spinlock_t lock_queue; // lock for DOT11_EnQueue2/DOT11_DeQueue2/enque/dequeue ++ spinlock_t lock_Rreq; // lock for rreq_retry. Some function like aodv_expire/tx use lock_queue simultaneously ++// spinlock_t lock_meshlist; ++ ++ // struct _DOT11_QUEUE *pevent_queue; ///< 802.11 QUEUEµ²ºc ++ // struct hash_table *pathsel_table; // GANTOE ++ //tsananiu ++ struct _DOT11_QUEUE *pathsel_queue; ///< 802.11 QUEUEµ²ºc ++ ++ //tsananiu end ++ ++ //add by shlu 20070518 ++ unsigned char RreqMAC[AODV_RREQ_TABLE_SIZE][6]; ++ unsigned int RreqBegin; ++ unsigned int RreqEnd; ++ ++#if defined(MESH_ROLE_ROOT) || defined(MESH_ROLE_PORTAL) ++#define MAX_SZ_BAD_MAC 3 ++ unsigned char BadMac[MAX_SZ_BAD_MAC][MACADDRLEN]; ++ int idx_BadMac; ++#endif // MESH_ROLE_ROOT || MESH_ROLE_PORTAL ++ ++ //------------- ++ unsigned char root_mac[MACADDRLEN]; ++ struct mesh_info dot11MeshInfo; // extrated from wifi_mib (ieee802_mib.h) ++ struct hash_table *proxy_table, *mesh_rreq_retry_queue; //GANTOE //GANTOE ++ struct hash_table *pathsel_table; // add by chuangch 2007.09.13 ++ // add by Jason ++ struct mpp_tb *pann_mpp_tb; ++ ++ struct timer_list expire_timer; // 1sec timer ++ ++ struct timer_list beacon_timer; // 1sec timer ++ struct list_head stat_hash[MAX_NETWORK_COUNT]; // sta_info hash table (aid_obj) ++ ++ struct list_head meshList[MAX_CHANNEL_NUMBER]; ++ int scanMode; ++ ++ struct { ++ struct ieee80211_network *pstat; ++ unsigned char hwaddr[MACADDRLEN]; ++ } stainfo_cache; ++ ++ // The following elements are used by 802.11s. ++ // For copyright-pretection, we use an independent (binary) module. ++ // Note that it can also be put either under r8180_priv or ieee80211_device. The adv of put under ++ // r8180_priv is to get "higher encapsulation". On the other hand, r8180_priv was originally designed ++ // for "hardward specific." ++ char mesh_mac_filter_allow[8][13]; ++ char mesh_mac_filter_deny[8][13]; ++ ++ struct MESH_Share meshare; // mesh share data ++ ++ struct { ++ ++ int prev_iw_mode; // Save this->iw_mode for r8180_wx->r8180_wx_enable_mesh. No init requirement ++ ++ struct MESH_Profile mesh_profile; // contains MESHID ++ ++ struct mesh_info dot11MeshInfo; // contains meshMaxAssocNum ++ ++ struct net_device_stats mesh_stats; ++ ++ UINT8 mesh_Version; // ¨Ï¥Îªºª©¥» ++ // WLAN Mesh Capability ++ INT16 mesh_PeerCAP_cap; // peer capability-Cap number (¦³¸¹¼Æ) ++ UINT8 mesh_PeerCAP_flags; // peer capability-flags ++ UINT8 mesh_PowerSaveCAP; // Power Save capability ++ UINT8 mesh_SyncCAP; // Synchronization capability ++ UINT8 mesh_MDA_CAP; // MDA capability ++ UINT32 mesh_ChannelPrecedence; // Channel Precedence ++ ++ // neighbor -> candidate neighbor, if mesh_available_peerlink > 0, page 56, D0.02 ++ UINT8 mesh_AvailablePeerLink; // ¦¹¬O§_¦³»Ý­n?(¦]¥¦µ¥¦P©ó mesh_PeerCAP)=>¼È ®É«O ¯d ++ ++ UINT8 mesh_HeaderFlags; // mesh header ¤ºªº mesh flags field ++ ++ // MKD domain element [MKDDIE] ++ UINT8 mesh_MKD_DomainID[6]; ++ UINT8 mesh_MKDDIE_SecurityConfiguration; ++ ++ // EMSA Handshake element [EMSAIE] ++ UINT8 mesh_EMSAIE_ANonce[32]; ++ UINT8 mesh_EMSAIE_SNonce[32]; ++ UINT8 mesh_EMSAIE_MA_ID[6]; ++ UINT16 mesh_EMSAIE_MIC_Control; ++ UINT8 mesh_EMSAIE_MIC[16]; ++ ++ struct timer_list mesh_peer_link_timer; ///< ¹ï©|¥¼³s ½u(»P³s½u°h¦Ü¥¼³s½u) MP mesh_unEstablish_hdr §@ peer link time out ++ ++// struct timer_list mesh_beacon_timer; ++ // mesh_unEstablish_hdr: ++ // It is a list structure, only stores unEstablish (or Establish -> unEstablish [MP_HOLDING])MP entry ++ // Each entry is a pointer pointing to an entry in "stat_info->mesh_mp_ptr" ++ // and removed by successful "Peer link setup" or "Expired" ++ struct list_head mesh_unEstablish_hdr; ++ ++ // mesh_mp_hdr: ++ // It is a list of MP/MAP/MPP who has already passed "Peer link setup" ++ // Each entry is a pointer pointing to an entry in "stat_info->mesh_mp_ptr" ++ // Every entry is inserted by "successful peer link setup" ++ // and removed by "Expired" ++ struct list_head mesh_mp_hdr; ++ ++ } mesh; ++ ++ int iCurChannel; // remember the working channel ++}; ++ ++// Stanley, 04/23/07 ++// The following mode is used by ieee80211_device->iw_mode ++// Although it is better to put the definition under linux/wireless.h (or wireless_copy.h), it is a system file ++// that we shouldn't modify directly. ++#define IW_MODE_MESH 11 /* 802.11s mesh mode */ ++ ++// Default MESHID ++#define IEEE80211S_DEFAULT_MESHID "802.11s" ++ ++// callback for 802.11s ++extern short rtl8187_patch_ieee80211_probe_req_1 (struct ieee80211_device *ieee); ++extern u8* rtl8187_patch_ieee80211_probe_req_2 (struct ieee80211_device *ieee, struct sk_buff *skb, u8 *tag); ++ ++// wx ++extern int rtl8187_patch_r8180_wx_get_meshinfo(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++extern int rtl8187_patch_r8180_wx_enable_mesh(struct net_device *dev); ++extern int rtl8187_patch_r8180_wx_disable_mesh(struct net_device *dev); ++extern int rtl8187_patch_r8180_wx_wx_set_meshID(struct net_device *dev, char *ext,unsigned char channel); ++extern void rtl8187_patch_r8180_wx_set_channel (struct ieee80211_device *ieee, int ch); ++extern int rtl8187_patch_r8180_wx_set_add_mac_allow(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++extern int rtl8187_patch_r8180_wx_set_del_mac_allow(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++extern int rtl8187_patch_r8180_wx_set_add_mac_deny(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++extern int rtl8187_patch_r8180_wx_set_del_mac_deny(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++extern int rtl8187_patch_r8180_wx_get_mac_allow(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++extern int rtl8187_patch_r8180_wx_get_mac_deny(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++ ++extern int rtl8187_patch_r8180_wx_get_mesh_list(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++extern int rtl8187_patch_r8180_wx_mesh_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++extern int rtl8187_patch_r8180_wx_get_selected_mesh(struct net_device *dev, int en, char *cho, char* id); ++//by amy for networkmanager UI ++extern int rtl8187_patch_r8180_wx_get_selected_mesh_channel(struct net_device *dev, char *extmeshid, char *cho); ++//by amy for networkmanager UI ++// osdep ++extern int rtl8187_patch_ieee80211_start_protocol (struct ieee80211_device *ieee); ++extern u8 rtl8187_patch_rtl8180_up(struct mshclass *priv); ++extern void rtl8187_patch_ieee80211_stop_protocol(struct ieee80211_device *ieee); ++ ++// issue_assocreq_MP ++extern void rtl8187_patch_ieee80211_association_req_1 (struct ieee80211_assoc_request_frame *hdr); ++extern u8* rtl8187_patch_ieee80211_association_req_2 (struct ieee80211_device *ieee, struct ieee80211_network *pstat, struct sk_buff *skb); ++ ++// OnAssocReq_MP ++extern int rtl8187_patch_ieee80211_rx_frame_softmac_on_assoc_req (struct ieee80211_device *ieee, struct sk_buff *skb); ++ ++// issue_assocrsp_MP ++extern void rtl8187_patch_ieee80211_assoc_resp_by_net_1 (struct ieee80211_assoc_response_frame *assoc); ++u8* rtl8187_patch_ieee80211_assoc_resp_by_net_2 (struct ieee80211_device *ieee, struct ieee80211_network *pstat, int pkt_type, struct sk_buff *skb); ++ ++// OnAssocRsp_MP ++extern int rtl8187_patch_ieee80211_rx_frame_softmac_on_assoc_rsp (struct ieee80211_device *ieee, struct sk_buff *skb); ++ ++ ++extern int rtl8187_patch_ieee80211_rx_frame_softmac_on_auth(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats); ++extern int rtl8187_patch_ieee80211_rx_frame_softmac_on_deauth(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats); ++extern unsigned int rtl8187_patch_ieee80211_process_probe_response_1( struct ieee80211_device *ieee, struct ieee80211_probe_response *beacon, struct ieee80211_rx_stats *stats); ++extern void rtl8187_patch_ieee80211_rx_mgt_on_probe_req( struct ieee80211_device *ieee, struct ieee80211_probe_request *beacon, struct ieee80211_rx_stats *stats); ++extern void rtl8187_patch_ieee80211_rx_mgt_update_expire ( struct ieee80211_device *ieee, struct sk_buff *skb); ++ ++// set channel ++extern int rtl8187_patch_ieee80211_ext_stop_scan_wq_set_channel (struct ieee80211_device *ieee); ++ ++// on rx (rx isr) ++extern int rtl8187_patch_ieee80211_rx_on_rx (struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats, u16 type, u16 stype); ++ ++// r8187_core ++// handle ioctl ++extern int rtl8187_patch_rtl8180_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); ++// create proc ++extern void rtl8187_patch_create_proc(struct r8180_priv *priv); ++extern void rtl8187_patch_remove_proc(struct r8180_priv *priv); ++ ++// tx, xmit ++// locked by ieee->lock. Call ieee80211_softmac_xmit afterward ++extern struct ieee80211_txb* rtl8187_patch_ieee80211_xmit (struct sk_buff *skb, struct net_device *dev); ++ ++// given a skb, output header's length ++extern int rtl8187_patch_ieee80211_rx_frame_get_hdrlen (struct ieee80211_device *ieee, struct sk_buff *skb); ++ ++// check the frame control field, return 0: not accept, 1: accept ++extern int rtl8187_patch_ieee80211_rx_is_valid_framectl (struct ieee80211_device *ieee, u16 fc, u16 type, u16 stype); ++ ++// process_dataframe ++extern int rtl8187_patch_ieee80211_rx_process_dataframe (struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats); ++ ++extern int rtl8187_patch_is_duplicate_packet (struct ieee80211_device *ieee, struct ieee80211_hdr *header, u16 type, u16 stype); ++ ++extern int rtl8187_patch_ieee80211_softmac_xmit_get_rate (struct ieee80211_device *ieee, struct sk_buff *skb); ++extern void ieee80211_start_mesh(struct ieee80211_device *ieee); ++#endif // _RTL8187_MESH_H_ +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/rtl_crypto.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/rtl_crypto.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/rtl_crypto.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/rtl_crypto.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,399 @@ ++/* ++ * Scatterlist Cryptographic API. ++ * ++ * Copyright (c) 2002 James Morris ++ * Copyright (c) 2002 David S. Miller (davem@redhat.com) ++ * ++ * Portions derived from Cryptoapi, by Alexander Kjeldaas ++ * and Nettle, by Niels Mé°ˆler. ++ * ++ * 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. ++ * ++ */ ++#ifndef _LINUX_CRYPTO_H ++#define _LINUX_CRYPTO_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define crypto_register_alg crypto_register_alg_rtl ++#define crypto_unregister_alg crypto_unregister_alg_rtl ++#define crypto_alloc_tfm crypto_alloc_tfm_rtl ++#define crypto_free_tfm crypto_free_tfm_rtl ++#define crypto_alg_available crypto_alg_available_rtl ++ ++/* ++ * Algorithm masks and types. ++ */ ++#define CRYPTO_ALG_TYPE_MASK 0x000000ff ++#define CRYPTO_ALG_TYPE_CIPHER 0x00000001 ++#define CRYPTO_ALG_TYPE_DIGEST 0x00000002 ++#define CRYPTO_ALG_TYPE_COMPRESS 0x00000004 ++ ++/* ++ * Transform masks and values (for crt_flags). ++ */ ++#define CRYPTO_TFM_MODE_MASK 0x000000ff ++#define CRYPTO_TFM_REQ_MASK 0x000fff00 ++#define CRYPTO_TFM_RES_MASK 0xfff00000 ++ ++#define CRYPTO_TFM_MODE_ECB 0x00000001 ++#define CRYPTO_TFM_MODE_CBC 0x00000002 ++#define CRYPTO_TFM_MODE_CFB 0x00000004 ++#define CRYPTO_TFM_MODE_CTR 0x00000008 ++ ++#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100 ++#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000 ++#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000 ++#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000 ++#define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000 ++#define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000 ++ ++/* ++ * Miscellaneous stuff. ++ */ ++#define CRYPTO_UNSPEC 0 ++#define CRYPTO_MAX_ALG_NAME 64 ++ ++struct scatterlist; ++ ++/* ++ * Algorithms: modular crypto algorithm implementations, managed ++ * via crypto_register_alg() and crypto_unregister_alg(). ++ */ ++struct cipher_alg { ++ unsigned int cia_min_keysize; ++ unsigned int cia_max_keysize; ++ int (*cia_setkey)(void *ctx, const u8 *key, ++ unsigned int keylen, u32 *flags); ++ void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src); ++ void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src); ++}; ++ ++struct digest_alg { ++ unsigned int dia_digestsize; ++ void (*dia_init)(void *ctx); ++ void (*dia_update)(void *ctx, const u8 *data, unsigned int len); ++ void (*dia_final)(void *ctx, u8 *out); ++ int (*dia_setkey)(void *ctx, const u8 *key, ++ unsigned int keylen, u32 *flags); ++}; ++ ++struct compress_alg { ++ int (*coa_init)(void *ctx); ++ void (*coa_exit)(void *ctx); ++ int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen, ++ u8 *dst, unsigned int *dlen); ++ int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen, ++ u8 *dst, unsigned int *dlen); ++}; ++ ++#define cra_cipher cra_u.cipher ++#define cra_digest cra_u.digest ++#define cra_compress cra_u.compress ++ ++struct crypto_alg { ++ struct list_head cra_list; ++ u32 cra_flags; ++ unsigned int cra_blocksize; ++ unsigned int cra_ctxsize; ++ const char cra_name[CRYPTO_MAX_ALG_NAME]; ++ ++ union { ++ struct cipher_alg cipher; ++ struct digest_alg digest; ++ struct compress_alg compress; ++ } cra_u; ++ ++ struct module *cra_module; ++}; ++ ++/* ++ * Algorithm registration interface. ++ */ ++int crypto_register_alg(struct crypto_alg *alg); ++int crypto_unregister_alg(struct crypto_alg *alg); ++ ++/* ++ * Algorithm query interface. ++ */ ++int crypto_alg_available(const char *name, u32 flags); ++ ++/* ++ * Transforms: user-instantiated objects which encapsulate algorithms ++ * and core processing logic. Managed via crypto_alloc_tfm() and ++ * crypto_free_tfm(), as well as the various helpers below. ++ */ ++struct crypto_tfm; ++ ++struct cipher_tfm { ++ void *cit_iv; ++ unsigned int cit_ivsize; ++ u32 cit_mode; ++ int (*cit_setkey)(struct crypto_tfm *tfm, ++ const u8 *key, unsigned int keylen); ++ int (*cit_encrypt)(struct crypto_tfm *tfm, ++ struct scatterlist *dst, ++ struct scatterlist *src, ++ unsigned int nbytes); ++ int (*cit_encrypt_iv)(struct crypto_tfm *tfm, ++ struct scatterlist *dst, ++ struct scatterlist *src, ++ unsigned int nbytes, u8 *iv); ++ int (*cit_decrypt)(struct crypto_tfm *tfm, ++ struct scatterlist *dst, ++ struct scatterlist *src, ++ unsigned int nbytes); ++ int (*cit_decrypt_iv)(struct crypto_tfm *tfm, ++ struct scatterlist *dst, ++ struct scatterlist *src, ++ unsigned int nbytes, u8 *iv); ++ void (*cit_xor_block)(u8 *dst, const u8 *src); ++}; ++ ++struct digest_tfm { ++ void (*dit_init)(struct crypto_tfm *tfm); ++ void (*dit_update)(struct crypto_tfm *tfm, ++ struct scatterlist *sg, unsigned int nsg); ++ void (*dit_final)(struct crypto_tfm *tfm, u8 *out); ++ void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg, ++ unsigned int nsg, u8 *out); ++ int (*dit_setkey)(struct crypto_tfm *tfm, ++ const u8 *key, unsigned int keylen); ++#ifdef CONFIG_CRYPTO_HMAC ++ void *dit_hmac_block; ++#endif ++}; ++ ++struct compress_tfm { ++ int (*cot_compress)(struct crypto_tfm *tfm, ++ const u8 *src, unsigned int slen, ++ u8 *dst, unsigned int *dlen); ++ int (*cot_decompress)(struct crypto_tfm *tfm, ++ const u8 *src, unsigned int slen, ++ u8 *dst, unsigned int *dlen); ++}; ++ ++#define crt_cipher crt_u.cipher ++#define crt_digest crt_u.digest ++#define crt_compress crt_u.compress ++ ++struct crypto_tfm { ++ ++ u32 crt_flags; ++ ++ union { ++ struct cipher_tfm cipher; ++ struct digest_tfm digest; ++ struct compress_tfm compress; ++ } crt_u; ++ ++ struct crypto_alg *__crt_alg; ++}; ++ ++/* ++ * Transform user interface. ++ */ ++ ++/* ++ * crypto_alloc_tfm() will first attempt to locate an already loaded algorithm. ++ * If that fails and the kernel supports dynamically loadable modules, it ++ * will then attempt to load a module of the same name or alias. A refcount ++ * is grabbed on the algorithm which is then associated with the new transform. ++ * ++ * crypto_free_tfm() frees up the transform and any associated resources, ++ * then drops the refcount on the associated algorithm. ++ */ ++struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags); ++void crypto_free_tfm(struct crypto_tfm *tfm); ++ ++/* ++ * Transform helpers which query the underlying algorithm. ++ */ ++static inline const char *crypto_tfm_alg_name(struct crypto_tfm *tfm) ++{ ++ return tfm->__crt_alg->cra_name; ++} ++ ++static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm) ++{ ++ struct crypto_alg *alg = tfm->__crt_alg; ++ ++ if (alg->cra_module) ++ return alg->cra_module->name; ++ else ++ return NULL; ++} ++ ++static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm) ++{ ++ return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK; ++} ++ ++static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); ++ return tfm->__crt_alg->cra_cipher.cia_min_keysize; ++} ++ ++static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); ++ return tfm->__crt_alg->cra_cipher.cia_max_keysize; ++} ++ ++static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); ++ return tfm->crt_cipher.cit_ivsize; ++} ++ ++static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm) ++{ ++ return tfm->__crt_alg->cra_blocksize; ++} ++ ++static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); ++ return tfm->__crt_alg->cra_digest.dia_digestsize; ++} ++ ++/* ++ * API wrappers. ++ */ ++static inline void crypto_digest_init(struct crypto_tfm *tfm) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); ++ tfm->crt_digest.dit_init(tfm); ++} ++ ++static inline void crypto_digest_update(struct crypto_tfm *tfm, ++ struct scatterlist *sg, ++ unsigned int nsg) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); ++ tfm->crt_digest.dit_update(tfm, sg, nsg); ++} ++ ++static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); ++ tfm->crt_digest.dit_final(tfm, out); ++} ++ ++static inline void crypto_digest_digest(struct crypto_tfm *tfm, ++ struct scatterlist *sg, ++ unsigned int nsg, u8 *out) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); ++ tfm->crt_digest.dit_digest(tfm, sg, nsg, out); ++} ++ ++static inline int crypto_digest_setkey(struct crypto_tfm *tfm, ++ const u8 *key, unsigned int keylen) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); ++ if (tfm->crt_digest.dit_setkey == NULL) ++ return -ENOSYS; ++ return tfm->crt_digest.dit_setkey(tfm, key, keylen); ++} ++ ++static inline int crypto_cipher_setkey(struct crypto_tfm *tfm, ++ const u8 *key, unsigned int keylen) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); ++ return tfm->crt_cipher.cit_setkey(tfm, key, keylen); ++} ++ ++static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm, ++ struct scatterlist *dst, ++ struct scatterlist *src, ++ unsigned int nbytes) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); ++ return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes); ++} ++ ++static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm, ++ struct scatterlist *dst, ++ struct scatterlist *src, ++ unsigned int nbytes, u8 *iv) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); ++ BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); ++ return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv); ++} ++ ++static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, ++ struct scatterlist *dst, ++ struct scatterlist *src, ++ unsigned int nbytes) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); ++ return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes); ++} ++ ++static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm, ++ struct scatterlist *dst, ++ struct scatterlist *src, ++ unsigned int nbytes, u8 *iv) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); ++ BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); ++ return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv); ++} ++ ++static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm, ++ const u8 *src, unsigned int len) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); ++ memcpy(tfm->crt_cipher.cit_iv, src, len); ++} ++ ++static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm, ++ u8 *dst, unsigned int len) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); ++ memcpy(dst, tfm->crt_cipher.cit_iv, len); ++} ++ ++static inline int crypto_comp_compress(struct crypto_tfm *tfm, ++ const u8 *src, unsigned int slen, ++ u8 *dst, unsigned int *dlen) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); ++ return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen); ++} ++ ++static inline int crypto_comp_decompress(struct crypto_tfm *tfm, ++ const u8 *src, unsigned int slen, ++ u8 *dst, unsigned int *dlen) ++{ ++ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); ++ return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen); ++} ++ ++/* ++ * HMAC support. ++ */ ++#ifdef CONFIG_CRYPTO_HMAC ++void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen); ++void crypto_hmac_update(struct crypto_tfm *tfm, ++ struct scatterlist *sg, unsigned int nsg); ++void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, ++ unsigned int *keylen, u8 *out); ++void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, ++ struct scatterlist *sg, unsigned int nsg, u8 *out); ++#endif /* CONFIG_CRYPTO_HMAC */ ++ ++#endif /* _LINUX_CRYPTO_H */ ++ +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/scatterwalk.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/scatterwalk.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/ieee80211/scatterwalk.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/ieee80211/scatterwalk.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,51 @@ ++/* ++ * Cryptographic API. ++ * ++ * Copyright (c) 2002 James Morris ++ * Copyright (c) 2002 Adam J. Richter ++ * Copyright (c) 2004 Jean-Luc Cooke ++ * ++ * 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. ++ * ++ */ ++ ++#ifndef _CRYPTO_SCATTERWALK_H ++#define _CRYPTO_SCATTERWALK_H ++#include ++#include ++ ++struct scatter_walk { ++ struct scatterlist *sg; ++ struct page *page; ++ void *data; ++ unsigned int len_this_page; ++ unsigned int len_this_segment; ++ unsigned int offset; ++}; ++ ++/* Define sg_next is an inline routine now in case we want to change ++ scatterlist to a linked list later. */ ++static inline struct scatterlist *sg_next(struct scatterlist *sg) ++{ ++ return sg + 1; ++} ++ ++static inline int scatterwalk_samebuf(struct scatter_walk *walk_in, ++ struct scatter_walk *walk_out, ++ void *src_p, void *dst_p) ++{ ++ return walk_in->page == walk_out->page && ++ walk_in->offset == walk_out->offset && ++ walk_in->data == src_p && walk_out->data == dst_p; ++} ++ ++void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch); ++void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg); ++int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out); ++void scatterwalk_map(struct scatter_walk *walk, int out); ++void scatterwalk_done(struct scatter_walk *walk, int out, int more); ++ ++#endif /* _CRYPTO_SCATTERWALK_H */ +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/Makefile linux-2.6.30.5/drivers/net/wireless/rtl8187b/Makefile +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/Makefile 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,41 @@ ++obj-$(CONFIG_RTL8187B) += rtl8187b.o ++ ++rtl8187b-objs := r8187_core.o \ ++ r8180_93cx6.o \ ++ r8180_wx.o \ ++ r8180_rtl8225.o \ ++ r8180_rtl8225z2.o \ ++ r8180_pm.o \ ++ r8180_dm.o \ ++ r8187_led.o \ ++ ieee80211/dot11d.o \ ++ ieee80211/ieee80211_softmac.o \ ++ ieee80211/ieee80211_rx.o \ ++ ieee80211/ieee80211_tx.o \ ++ ieee80211/ieee80211_wx.o \ ++ ieee80211/ieee80211_module.o \ ++ ieee80211/ieee80211_softmac_wx.o \ ++ ieee80211/ieee80211_crypt.o \ ++ ieee80211/ieee80211_crypt_tkip.o \ ++ ieee80211/ieee80211_crypt_ccmp.o \ ++ ieee80211/ieee80211_crypt_wep.o ++ ++EXTRA_CFLAGS += -DCONFIG_RTL8180_PM ++EXTRA_CFLAGS += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX ++EXTRA_CFLAGS += -DTHOMAS_BEACON -DTHOMAS_TASKLET -DTHOMAS_SKB -DTHOMAS_TURBO ++EXTRA_CFLAGS += -DJOHN_IOCTL ++EXTRA_CFLAGS += -DLED ++#EXTRA_CFLAGS += -DLED_SHIN ++EXTRA_CFLAGS += -DPOLLING_METHOD_FOR_RADIO ++#EXTRA_CFLAGS += -DSW_ANTE_DIVERSITY ++EXTRA_CFLAGS += -DCPU_64BIT ++EXTRA_CFLAGS += -DCONFIG_IPS ++#CFLAGS += -DJOHN_HWSEC -DJOHN_TKIP ++#CFLAGS += -DJOHN_DUMP_TX ++#EXTRA_CFLAGS += -DJOHN_DUMP_TXPKT ++ ++#Radio On/Off debug ++EXTRA_CFLAGS += -DCONFIG_RADIO_DEBUG ++ ++#for dot11d ++EXTRA_CFLAGS += -DENABLE_DOT11D +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/msh_class.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/msh_class.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/msh_class.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/msh_class.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,117 @@ ++/*! \file msh_class.h ++ \brief msh CLASS extension ++ ++ \date 2007/5/2 ++ \author Stanley Chang ++*/ ++ ++#ifndef _MESH_CLASS_HDR_H_ ++#define _MESH_CLASS_HDR_H_ ++ ++#include /* ETH_ALEN */ ++#include /* ARRAY_SIZE */ ++#include ++#include ++#include ++#include ++ ++#include "ieee80211/ieee80211.h" // for struct ieee80211-xxxx ++#include "r8187.h" // for struct r8180-priv ++ ++#define MAC_TABLE_SIZE 8 ++ ++struct mshclass { ++ struct r8180_priv * p8187; ++ ++ // callback functions ++ // ieee80211_softmac.c ++ int (*ext_patch_ieee80211_start_protocol) (struct ieee80211_device *ieee); // start special mode ++ ++ short (*ext_patch_ieee80211_probe_req_1) (struct ieee80211_device *ieee); // return = 0: no more phases, >0: another phase ++ u8* (*ext_patch_ieee80211_probe_req_2) (struct ieee80211_device *ieee, struct sk_buff *skb, u8 *tag); // return tag ++ ++ void (*ext_patch_ieee80211_association_req_1) (struct ieee80211_assoc_request_frame *hdr); ++ u8* (*ext_patch_ieee80211_association_req_2) (struct ieee80211_device *ieee, struct ieee80211_network *pstat, struct sk_buff *skb); ++ ++ int (*ext_patch_ieee80211_rx_frame_softmac_on_assoc_req) (struct ieee80211_device *ieee, struct sk_buff *skb); ++ int (*ext_patch_ieee80211_rx_frame_softmac_on_assoc_rsp) (struct ieee80211_device *ieee, struct sk_buff *skb); ++ ++ void (*ext_patch_ieee80211_stop_protocol) (struct ieee80211_device *ieee); // stop timer ++ ++ void (*ext_patch_ieee80211_assoc_resp_by_net_1) (struct ieee80211_assoc_response_frame *assoc); ++ u8* (*ext_patch_ieee80211_assoc_resp_by_net_2) (struct ieee80211_device *ieee, struct ieee80211_network *pstat, int pkt_type, struct sk_buff *skb); ++ ++ int (*ext_patch_ieee80211_ext_stop_scan_wq_set_channel) (struct ieee80211_device *ieee); ++ ++ struct sk_buff* (*ext_patch_get_beacon_get_probersp)(struct ieee80211_device *ieee, u8 *dest, struct ieee80211_network *net); ++ ++ int (*ext_patch_ieee80211_softmac_xmit_get_rate) (struct ieee80211_device *ieee, struct sk_buff *skb); ++ int (*ext_patch_ieee80211_rx_frame_softmac_on_auth)(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats); ++ int (*ext_patch_ieee80211_rx_frame_softmac_on_deauth)(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats); ++//by amy for mesh ++ void (*ext_patch_ieee80211_start_mesh)(struct ieee80211_device *ieee); ++//by amy for mesh ++ /// r8180_wx.c ++ int (*ext_patch_r8180_wx_get_meshinfo) (struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++ int (*ext_patch_r8180_wx_enable_mesh) (struct net_device *dev); ++ int (*ext_patch_r8180_wx_disable_mesh) (struct net_device *dev); ++ int (*ext_patch_r8180_wx_set_meshID) ( struct net_device *dev, char *ext); ++//by amy for mesh ++ int (*ext_patch_r8180_wx_set_mesh_chan)(struct net_device *dev, unsigned char channel); ++//by amy for mesh ++ void (*ext_patch_r8180_wx_set_channel) (struct ieee80211_device *ieee, int ch); ++ ++ int (*ext_patch_r8180_wx_set_add_mac_allow) (struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++ int (*ext_patch_r8180_wx_set_del_mac_allow) (struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++ int (*ext_patch_r8180_wx_set_add_mac_deny) (struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++ int (*ext_patch_r8180_wx_set_del_mac_deny) (struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++ int (*ext_patch_r8180_wx_get_mac_allow) (struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++ int (*ext_patch_r8180_wx_get_mac_deny) (struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++ ++ int (*ext_patch_r8180_wx_get_mesh_list) (struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++ int (*ext_patch_r8180_wx_mesh_scan) (struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++ int (*ext_patch_r8180_wx_get_selected_mesh)(struct net_device *dev, int en, char *cho, char* id); ++//by amy for networkmanager UI ++ int (*ext_patch_r8180_wx_get_selected_mesh_channel)(struct net_device *dev, char* extmeshid, char *cho); ++//by amy for networkmanager UI ++ /// r8187_core.c ++ u8 (*ext_patch_rtl8180_up) (struct mshclass *priv); ++ ++ // ieee80211_rx.c ++ unsigned int (*ext_patch_ieee80211_process_probe_response_1) ( struct ieee80211_device *ieee, struct ieee80211_probe_response *beacon, struct ieee80211_rx_stats *stats); ++ void (*ext_patch_ieee80211_rx_mgt_on_probe_req) ( struct ieee80211_device *ieee, struct ieee80211_probe_request *beacon, struct ieee80211_rx_stats *stats); ++ ++ void (*ext_patch_ieee80211_rx_mgt_update_expire) ( struct ieee80211_device *ieee, struct sk_buff *skb); ++ ++ int (*ext_patch_ieee80211_rx_on_rx) (struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats, u16 type, u16 stype); ++ ++ int (*ext_patch_ieee80211_rx_frame_get_hdrlen) (struct ieee80211_device *ieee, struct sk_buff *skb); ++ ++ int (*ext_patch_ieee80211_rx_is_valid_framectl) (struct ieee80211_device *ieee, u16 fc, u16 type, u16 stype); ++ ++ // return > 0 is success. 0 when failed ++ int (*ext_patch_ieee80211_rx_process_dataframe) (struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats); ++ ++ int (*ext_patch_is_duplicate_packet) (struct ieee80211_device *ieee, struct ieee80211_hdr *header, u16 type, u16 stype); ++ /* added by david for setting acl dynamically */ ++ u8 (*ext_patch_ieee80211_acl_query) (struct ieee80211_device *ieee, u8 *sa); ++ ++ // r8187_core.c ++ int (*ext_patch_rtl8180_ioctl) (struct net_device *dev, struct ifreq *rq, int cmd); ++ void (*ext_patch_create_proc) (struct r8180_priv *priv); ++ void (*ext_patch_remove_proc) (struct r8180_priv *priv); ++ ++ // ieee80211_tx.c ++ ++ // locked by ieee->lock. Call ieee80211_softmac_xmit afterward ++ struct ieee80211_txb* (*ext_patch_ieee80211_xmit) (struct sk_buff *skb, struct net_device *dev); ++ ++ // DO NOT MODIFY ANY STRUCTURE BELOW THIS LINE ++ u8 priv[0]; // mshclass_priv; ++}; ++ ++extern void free_mshobj(struct mshclass **pObj); ++extern struct mshclass *alloc_mshobj(struct r8180_priv *caller_priv); ++ ++ ++#endif // _MESH_CLASS_HDR_H_ +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_93cx6.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_93cx6.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_93cx6.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_93cx6.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,146 @@ ++/* ++ This files contains card eeprom (93c46 or 93c56) programming routines, ++ memory is addressed by 16 bits words. ++ ++ This is part of rtl8180 OpenSource driver. ++ Copyright (C) Andrea Merello 2004 ++ Released under the terms of GPL (General Public Licence) ++ ++ Parts of this driver are based on the GPL part of the ++ official realtek driver. ++ ++ Parts of this driver are based on the rtl8180 driver skeleton ++ from Patric Schenke & Andres Salomon. ++ ++ Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver. ++ ++ We want to tanks the Authors of those projects and the Ndiswrapper ++ project Authors. ++*/ ++ ++#include "r8180_93cx6.h" ++ ++void eprom_cs(struct net_device *dev, short bit) ++{ ++ if(bit) ++ write_nic_byte(dev, EPROM_CMD, ++ (1<epromtype==EPROM_93c56){ ++ addr_str[7]=addr & 1; ++ addr_str[6]=addr & (1<<1); ++ addr_str[5]=addr & (1<<2); ++ addr_str[4]=addr & (1<<3); ++ addr_str[3]=addr & (1<<4); ++ addr_str[2]=addr & (1<<5); ++ addr_str[1]=addr & (1<<6); ++ addr_str[0]=addr & (1<<7); ++ addr_len=8; ++ }else{ ++ addr_str[5]=addr & 1; ++ addr_str[4]=addr & (1<<1); ++ addr_str[3]=addr & (1<<2); ++ addr_str[2]=addr & (1<<3); ++ addr_str[1]=addr & (1<<4); ++ addr_str[0]=addr & (1<<5); ++ addr_len=6; ++ } ++ eprom_cs(dev, 1); ++ eprom_ck_cycle(dev); ++ eprom_send_bits_string(dev, read_cmd, 3); ++ eprom_send_bits_string(dev, addr_str, addr_len); ++ ++ //keep chip pin D to low state while reading. ++ //I'm unsure if it is necessary, but anyway shouldn't hurt ++ eprom_w(dev, 0); ++ ++ for(i=0;i<16;i++){ ++ //eeprom needs a clk cycle between writing opcode&adr ++ //and reading data. (eeprom outs a dummy 0) ++ eprom_ck_cycle(dev); ++ ret |= (eprom_r(dev)<<(15-i)); ++ } ++ ++ eprom_cs(dev, 0); ++ eprom_ck_cycle(dev); ++ ++ //disable EPROM programming ++ write_nic_byte(dev, EPROM_CMD, ++ (EPROM_CMD_NORMAL< ++ Released under the terms of GPL (General Public Licence) ++ ++ Parts of this driver are based on the GPL part of the official realtek driver ++ Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon ++ Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver ++ ++ We want to tanks the Authors of such projects and the Ndiswrapper project Authors. ++*/ ++ ++/*This files contains card eeprom (93c46 or 93c56) programming routines*/ ++/*memory is addressed by WORDS*/ ++ ++#include "r8187.h" ++#include "r8180_hw.h" ++ ++#define EPROM_DELAY 10 ++ ++#define EPROM_ANAPARAM_ADDRLWORD 0xd ++#define EPROM_ANAPARAM_ADDRHWORD 0xe ++ ++#define EPROM_CHANNEL_PLAN 0x3 //0x6>>1 ++//0x77 BIT[0]0:use gpio 1 bit 1, 1:use gpio 1 bit 2. ++#define EPROM_SELECT_GPIO (0x77 >> 1) ++//#define EEPROM_COUNTRY_CODE 0x2E//87se channel plan is here ++ ++#define EPROM_RFCHIPID 0x6 ++#define EPROM_TXPW_BASE 0x05 ++#define EPROM_RFCHIPID_RTL8225U 5 ++#define EPROM_RFCHIPID_RTL8225U_VF 6 ++#define EPROM_RF_PARAM 0x4 ++#define EPROM_CONFIG2 0xc ++ ++#define EPROM_VERSION 0x1E ++#define MAC_ADR 0x7 ++ ++#define CIS 0x18 ++ ++#define EPROM_TXPW0 0x16 ++#define EPROM_TXPW2 0x1b ++#define EPROM_TXPW1 0x3d ++ ++ ++u32 eprom_read(struct net_device *dev,u32 addr); //reads a 16 bits word +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_dm.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_dm.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_dm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_dm.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,882 @@ ++/*++ ++Copyright (c) Realtek Semiconductor Corp. All rights reserved. ++ ++Module Name: ++ r8180_dig.c ++ ++Abstract: ++ Hardware dynamic mechanism for RTL8187B ++ ++Major Change History: ++ When Who What ++ ---------- --------------- ------------------------------- ++ 2006-11-15 david Created ++ ++Notes: ++ This file is ported from RTL8187B Windows driver. ++ ++ ++--*/ ++#include "r8180_dm.h" ++#include "r8180_hw.h" ++#include "r8180_rtl8225.h" ++ ++//================================================================================ ++// Local Constant. ++//================================================================================ ++#define Z1_HIPWR_UPPER_TH 99 ++#define Z1_HIPWR_LOWER_TH 70 ++#define Z2_HIPWR_UPPER_TH 99 ++#define Z2_HIPWR_LOWER_TH 90 ++ ++bool CheckDig(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct ieee80211_device *ieee = priv->ieee80211; ++ ++ if(ieee->state != IEEE80211_LINKED) ++ return false; ++ ++ if(priv->card_8187 == NIC_8187B) { ++ // ++ // We need to schedule dig workitem on either of the below mechanisms. ++ // By Bruce, 2007-06-01. ++ // ++ if(!priv->bDigMechanism && !priv->bCCKThMechanism) ++ return false; ++ ++ if(priv->CurrentOperaRate < 36) // Schedule Dig under all OFDM rates. By Bruce, 2007-06-01. ++ return false; ++ } else { ++ if(!priv->bDigMechanism) ++ return false; ++ ++ if(priv->CurrentOperaRate < 48) ++ return false; ++ } ++ return true; ++} ++ ++ ++// ++// Description: ++// Implementation of DIG for Zebra and Zebra2. ++// ++void DIG_Zebra(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ //PHAL_DATA_8187 pHalData = GetHalData8187(Adapter); ++ u16 CCKFalseAlarm, OFDMFalseAlarm; ++ u16 OfdmFA1, OfdmFA2; ++ int InitialGainStep = 7; // The number of initial gain stages. ++ int LowestGainStage = 4; // The capable lowest stage of performing dig workitem. ++ ++// printk("---------> DIG_Zebra()\n"); ++ ++ //Read only 1 byte because of HW bug. This is a temporal modification. Joseph ++ // Modify by Isaiah 2006-06-27 ++ if(priv->card_8187_Bversion == VERSION_8187B_B) ++ { ++ CCKFalseAlarm = 0; ++ OFDMFalseAlarm = (u16)(priv->FalseAlarmRegValue); ++ OfdmFA1 = 0x01; ++ OfdmFA2 = priv->RegDigOfdmFaUpTh; ++ } ++ else ++ { ++ CCKFalseAlarm = (u16)(priv->FalseAlarmRegValue & 0x0000ffff); ++ OFDMFalseAlarm = (u16)((priv->FalseAlarmRegValue >> 16) & 0x0000ffff); ++ OfdmFA1 = 0x15; ++ //OfdmFA2 = 0xC00; ++ OfdmFA2 = ((u16)(priv->RegDigOfdmFaUpTh)) << 8; ++ } ++ ++// printk("DIG**********CCK False Alarm: %#X \n",CCKFalseAlarm); ++// printk("DIG**********OFDM False Alarm: %#X \n",OFDMFalseAlarm); ++ ++ ++ ++ // The number of initial gain steps is different, by Bruce, 2007-04-13. ++ if(priv->card_8187 == NIC_8187) { ++ if (priv->InitialGain == 0 ) //autoDIG ++ { ++ switch( priv->rf_chip) ++ { ++ case RF_ZEBRA: ++ priv->InitialGain = 5; // m74dBm; ++ break; ++ case RF_ZEBRA2: ++ priv->InitialGain = 4; // m78dBm; ++ break; ++ default: ++ priv->InitialGain = 5; // m74dBm; ++ break; ++ } ++ } ++ InitialGainStep = 7; ++ if(priv->InitialGain > 7) ++ priv->InitialGain = 5; ++ LowestGainStage = 4; ++ } else { ++ if (priv->InitialGain == 0 ) //autoDIG ++ { // Advised from SD3 DZ, by Bruce, 2007-06-05. ++ priv->InitialGain = 4; // In 87B, m74dBm means State 4 (m82dBm) ++ } ++ if(priv->card_8187_Bversion != VERSION_8187B_B) ++ { // Advised from SD3 DZ, by Bruce, 2007-06-05. ++ OfdmFA1 = 0x20; ++ } ++ InitialGainStep = 8; ++ LowestGainStage = priv->RegBModeGainStage; // Lowest gain stage. ++ } ++ ++ if (OFDMFalseAlarm > OfdmFA1) ++ { ++ if (OFDMFalseAlarm > OfdmFA2) ++ { ++ priv->DIG_NumberFallbackVote++; ++ if (priv->DIG_NumberFallbackVote >1) ++ { ++ //serious OFDM False Alarm, need fallback ++ // By Bruce, 2007-03-29. ++ // if (pHalData->InitialGain < 7) // In 87B, m66dBm means State 7 (m74dBm) ++ if (priv->InitialGain < InitialGainStep) ++ { ++ priv->InitialGain = (priv->InitialGain + 1); ++ //printk("DIG**********OFDM False Alarm: %#X, OfdmFA1: %#X, OfdmFA2: %#X\n", OFDMFalseAlarm, OfdmFA1, OfdmFA2); ++ //printk("DIG+++++++ fallback OFDM:%d \n", priv->InitialGain); ++ UpdateInitialGain(dev); // 2005.01.06, by rcnjko. ++ } ++ priv->DIG_NumberFallbackVote = 0; ++ priv->DIG_NumberUpgradeVote=0; ++ } ++ } ++ else ++ { ++ if (priv->DIG_NumberFallbackVote) ++ priv->DIG_NumberFallbackVote--; ++ } ++ priv->DIG_NumberUpgradeVote=0; ++ } ++ else //OFDM False Alarm < 0x15 ++ { ++ if (priv->DIG_NumberFallbackVote) ++ priv->DIG_NumberFallbackVote--; ++ priv->DIG_NumberUpgradeVote++; ++ ++ if (priv->DIG_NumberUpgradeVote>9) ++ { ++ if (priv->InitialGain > LowestGainStage) // In 87B, m78dBm means State 4 (m864dBm) ++ { ++ priv->InitialGain = (priv->InitialGain - 1); ++ //printk("DIG**********OFDM False Alarm: %#X, OfdmFA1: %#X, OfdmFA2: %#X\n", OFDMFalseAlarm, OfdmFA1, OfdmFA2); ++ //printk("DIG--------- Upgrade OFDM:%d \n", priv->InitialGain); ++ UpdateInitialGain(dev); // 2005.01.06, by rcnjko. ++ } ++ priv->DIG_NumberFallbackVote = 0; ++ priv->DIG_NumberUpgradeVote=0; ++ } ++ } ++ ++// printk("DIG+++++++ OFDM:%d\n", priv->InitialGain); ++// printk("<--------- DIG_Zebra()\n"); ++} ++ ++// ++// Description: ++// Dispatch DIG implementation according to RF. ++// ++void DynamicInitGain(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ ++ switch(priv->rf_chip) ++ { ++ case RF_ZEBRA: ++ case RF_ZEBRA2: // [AnnieWorkaround] For Zebra2, 2005-08-01. ++ //case RF_ZEBRA4: ++ DIG_Zebra(dev); ++ break; ++ ++ default: ++ printk("DynamicInitGain(): unknown RFChipID(%d) !!!\n", priv->rf_chip); ++ break; ++ } ++} ++ ++// By Bruce, 2007-03-29. ++// ++// Description: ++// Dispatch CCK Power Detection implementation according to RF. ++// ++void DynamicCCKThreshold(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ u16 CCK_Up_Th; ++ u16 CCK_Lw_Th; ++ u16 CCKFalseAlarm; ++ ++ printk("=====>DynamicCCKThreshold()\n"); ++ ++ CCK_Up_Th = priv->CCKUpperTh; ++ CCK_Lw_Th = priv->CCKLowerTh; ++ CCKFalseAlarm = (u16)((priv->FalseAlarmRegValue & 0x0000ffff) >> 8); // We only care about the higher byte. ++ printk("DynamicCCKThreshold(): CCK Upper Threshold: 0x%02X, Lower Threshold: 0x%02X, CCKFalseAlarmHighByte: 0x%02X\n", CCK_Up_Th, CCK_Lw_Th, CCKFalseAlarm); ++ ++ if(priv->StageCCKTh < 3 && CCKFalseAlarm >= CCK_Up_Th) ++ { ++ priv->StageCCKTh ++; ++ UpdateCCKThreshold(dev); ++ } ++ else if(priv->StageCCKTh > 0 && CCKFalseAlarm <= CCK_Lw_Th) ++ { ++ priv->StageCCKTh --; ++ UpdateCCKThreshold(dev); ++ } ++ ++ printk("<=====DynamicCCKThreshold()\n"); ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void rtl8180_hw_dig_wq (struct work_struct *work) ++{ ++ struct delayed_work *dwork = container_of(work,struct delayed_work,work); ++ struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_dig_wq); ++ struct net_device *dev = ieee->dev; ++#else ++void rtl8180_hw_dig_wq(struct net_device *dev) ++{ ++ // struct r8180_priv *priv = ieee80211_priv(dev); ++#endif ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ // Read CCK and OFDM False Alarm. ++ if(priv->card_8187_Bversion == VERSION_8187B_B) { ++ // Read only 1 byte because of HW bug. This is a temporal modification. Joseph ++ // Modify by Isaiah 2006-06-27 ++ priv->FalseAlarmRegValue = (u32)read_nic_byte(dev, (OFDM_FALSE_ALARM+1)); ++ } else { ++ priv->FalseAlarmRegValue = read_nic_dword(dev, CCK_FALSE_ALARM); ++ } ++ ++ // Adjust Initial Gain dynamically. ++ if(priv->bDigMechanism) { ++ DynamicInitGain(dev); ++ } ++ ++ // ++ // Move from DynamicInitGain to be independent of the OFDM DIG mechanism, by Bruce, 2007-06-01. ++ // ++ if(priv->card_8187 == NIC_8187B) { ++ // By Bruce, 2007-03-29. ++ // Dynamically update CCK Power Detection Threshold. ++ if(priv->bCCKThMechanism) ++ { ++ DynamicCCKThreshold(dev); ++ } ++ } ++} ++ ++void SetTxPowerLevel8187(struct net_device *dev, short chan) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ switch(priv->rf_chip) ++ { ++ case RF_ZEBRA: ++ rtl8225_SetTXPowerLevel(dev,chan); ++ break; ++ ++ case RF_ZEBRA2: ++ //case RF_ZEBRA4: ++ rtl8225z2_SetTXPowerLevel(dev,chan); ++ break; ++ } ++} ++ ++// ++// Description: ++// Check if input power signal strength exceeds maximum input power threshold ++// of current HW. ++// If yes, we set our HW to high input power state: ++// RX: always force TR switch to SW Tx mode to reduce input power. ++// TX: turn off smaller Tx output power (see RtUsbCheckForHang). ++// ++// If no, we restore our HW to normal input power state: ++/// RX: restore TR switch to HW controled mode. ++// TX: restore TX output power (see RtUsbCheckForHang). ++// ++// TODO: ++// 1. Tx power control shall not be done in Platform-dependent timer (e.g. RtUsbCheckForHang). ++// 2. Allow these threshold adjustable by RF SD. ++// ++void DoRxHighPower(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ TR_SWITCH_STATE TrSwState; ++ u16 HiPwrUpperTh = 0; ++ u16 HiPwrLowerTh = 0; ++ u16 RSSIHiPwrUpperTh = 0; ++ u16 RSSIHiPwrLowerTh = 0; ++ ++ //87S remove TrSwitch mechanism ++ if((priv->card_8187 == NIC_8187B)||(priv->card_8187 == NIC_8187)) { ++ ++ //printk("----> DoRxHighPower()\n"); ++ ++ // ++ // Get current TR switch setting. ++ // ++ //Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_TR_SWITCH, (pu1Byte)(&TrSwState)); ++ TrSwState = priv->TrSwitchState; ++ ++ // ++ // Determine threshold according to RF type. ++ // ++ switch(priv->rf_chip) ++ { ++ case RF_ZEBRA: ++ HiPwrUpperTh = Z1_HIPWR_UPPER_TH; ++ HiPwrLowerTh = Z1_HIPWR_LOWER_TH; ++ printk("DoRxHighPower(): RF_ZEBRA, Upper Threshold: %d LOWER Threshold: %d\n", ++ HiPwrUpperTh, HiPwrLowerTh); ++ break; ++ ++ case RF_ZEBRA2: ++ if((priv->card_8187 == NIC_8187)) { ++ HiPwrUpperTh = Z2_HIPWR_UPPER_TH; ++ HiPwrLowerTh = Z2_HIPWR_LOWER_TH; ++ } else { ++ // By Bruce, 2007-04-11. ++ // HiPwrUpperTh = Z2_HIPWR_UPPER_TH; ++ // HiPwrLowerTh = Z2_HIPWR_LOWER_TH; ++ ++ HiPwrUpperTh = priv->Z2HiPwrUpperTh; ++ HiPwrLowerTh = priv->Z2HiPwrLowerTh; ++ HiPwrUpperTh = HiPwrUpperTh * 10; ++ HiPwrLowerTh = HiPwrLowerTh * 10; ++ ++ RSSIHiPwrUpperTh = priv->Z2RSSIHiPwrUpperTh; ++ RSSIHiPwrLowerTh = priv->Z2RSSIHiPwrLowerTh; ++ //printk("DoRxHighPower(): RF_ZEBRA2, Upper Threshold: %d LOWER Threshold: %d, RSSI Upper Th: %d, RSSI Lower Th: %d\n",HiPwrUpperTh, HiPwrLowerTh, RSSIHiPwrUpperTh, RSSIHiPwrLowerTh); ++ } ++ break; ++ ++ default: ++ printk("DoRxHighPower(): Unknown RFChipID(%d), UndecoratedSmoothedSS(%d), TrSwState(%d)!!!\n", ++ priv->rf_chip, priv->UndecoratedSmoothedSS, TrSwState); ++ return; ++ break; ++ } ++ ++ /*printk(">>>>>>>>>>Set TR switch to software control, UndecoratedSmoothedSS:%d, CurCCKRSSI = %d\n",\ ++ priv->UndecoratedSmoothedSS, priv->CurCCKRSSI); ++ */ ++ if((priv->card_8187 == NIC_8187)) { ++ // ++ // Perform Rx part High Power Mechanism by UndecoratedSmoothedSS. ++ // ++ if (priv->UndecoratedSmoothedSS > HiPwrUpperTh) ++ { // High input power state. ++ if( priv->TrSwitchState == TR_HW_CONTROLLED ) ++ { ++ /* printk(">>>>>>>>>>Set TR switch to software control, UndecoratedSmoothedSS:%d \n", \ ++ priv->UndecoratedSmoothedSS); ++ // printk(">>>>>>>>>> TR_SW_TX\n"); ++ */ ++ write_nic_byte(dev, RFPinsSelect, ++ (u8)(priv->wMacRegRfPinsSelect | TR_SW_MASK_8187 )); ++ write_nic_byte(dev, RFPinsOutput, ++ (u8)((priv->wMacRegRfPinsOutput&(~TR_SW_MASK_8187))|TR_SW_MASK_TX_8187)); ++ priv->TrSwitchState = TR_SW_TX; ++ priv->bToUpdateTxPwr = true; ++ } ++ } ++ else if (priv->UndecoratedSmoothedSS < HiPwrLowerTh) ++ { // Normal input power state. ++ if( priv->TrSwitchState == TR_SW_TX) ++ { ++ /* printk("<<<<<<<<<<UndecoratedSmoothedSS); ++ // printk("<<<<<<<<<< TR_HW_CONTROLLED\n"); ++ */ ++ write_nic_byte(dev, RFPinsOutput, (u8)(priv->wMacRegRfPinsOutput)); ++ write_nic_byte(dev, RFPinsSelect, (u8)(priv->wMacRegRfPinsSelect)); ++ priv->TrSwitchState = TR_HW_CONTROLLED; ++ priv->bToUpdateTxPwr = true; ++ } ++ } ++ }else { ++ /*printk("=====>TrSwState = %s\n", (TrSwState==TR_HW_CONTROLLED)?"TR_HW_CONTROLLED":"TR_SW_TX"); ++ //printk("UndecoratedSmoothedSS:%d, CurCCKRSSI = %d\n",priv->UndecoratedSmoothedSS, priv->CurCCKRSSI); */ ++ // Asked by SD3 DZ, by Bruce, 2007-04-12. ++ if(TrSwState == TR_HW_CONTROLLED) ++ { ++ if((priv->UndecoratedSmoothedSS > HiPwrUpperTh) || ++ (priv->bCurCCKPkt && (priv->CurCCKRSSI > RSSIHiPwrUpperTh))) ++ { ++ //printk("===============================> high power!\n"); ++ write_nic_byte(dev, RFPinsSelect, (u8)(priv->wMacRegRfPinsSelect|TR_SW_MASK_8187 )); ++ write_nic_byte(dev, RFPinsOutput, ++ (u8)((priv->wMacRegRfPinsOutput&(~TR_SW_MASK_8187))|TR_SW_MASK_TX_8187)); ++ priv->TrSwitchState = TR_SW_TX; ++ priv->bToUpdateTxPwr = true; ++ } ++ } ++ else ++ { ++ if((priv->UndecoratedSmoothedSS < HiPwrLowerTh) && ++ (!priv->bCurCCKPkt || priv->CurCCKRSSI < RSSIHiPwrLowerTh)) ++ { ++ write_nic_byte(dev, RFPinsOutput, (u8)(priv->wMacRegRfPinsOutput)); ++ write_nic_byte(dev, RFPinsSelect, (u8)(priv->wMacRegRfPinsSelect)); ++ priv->TrSwitchState = TR_HW_CONTROLLED; ++ priv->bToUpdateTxPwr = true; ++ } ++ } ++ //printk("<=======TrSwState = %s\n", (TrSwState==TR_HW_CONTROLLED)?"TR_HW_CONTROLLED":"TR_SW_TX"); ++ } ++ //printk("<---- DoRxHighPower()\n"); ++ } ++} ++ ++ ++// ++// Description: ++// Callback function of UpdateTxPowerWorkItem. ++// Because of some event happend, e.g. CCX TPC, High Power Mechanism, ++// We update Tx power of current channel again. ++// ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void rtl8180_tx_pw_wq (struct work_struct *work) ++{ ++ struct delayed_work *dwork = container_of(work,struct delayed_work,work); ++ struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,tx_pw_wq); ++ struct net_device *dev = ieee->dev; ++#else ++void rtl8180_tx_pw_wq(struct net_device *dev) ++{ ++ // struct r8180_priv *priv = ieee80211_priv(dev); ++#endif ++ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ //printk("----> UpdateTxPowerWorkItemCallback()\n"); ++ ++ if(priv->bToUpdateTxPwr) ++ { ++ //printk("DoTxHighPower(): schedule UpdateTxPowerWorkItem......\n"); ++ priv->bToUpdateTxPwr = false; ++ SetTxPowerLevel8187(dev, priv->chan); ++ } ++ ++ DoRxHighPower(dev); ++ //printk("<---- UpdateTxPowerWorkItemCallback()\n"); ++} ++ ++// ++// Description: ++// Return TRUE if we shall perform High Power Mecahnism, FALSE otherwise. ++// ++bool CheckHighPower(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ struct ieee80211_device *ieee = priv->ieee80211; ++ ++ if(!priv->bRegHighPowerMechanism) ++ { ++ return false; ++ } ++ ++ if((ieee->state == IEEE80211_LINKED_SCANNING)||(ieee->state == IEEE80211_MESH_SCANNING)) ++ { ++ return false; ++ } ++ ++ return true; ++} ++ ++#ifdef SW_ANTE_DIVERSITY ++ ++#define ANTENNA_DIVERSITY_TIMER_PERIOD 1000 // 1000 m ++ ++void ++SwAntennaDiversityRxOk8185( ++ struct net_device *dev, ++ u8 SignalStrength ++ ) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ ++ //printk("+SwAntennaDiversityRxOk8185: RxSs: %d\n", SignalStrength); ++ ++ priv->AdRxOkCnt++; ++ ++ if( priv->AdRxSignalStrength != -1) ++ { ++ priv->AdRxSignalStrength = ((priv->AdRxSignalStrength*7) + (SignalStrength*3)) / 10; ++ } ++ else ++ { // Initialization case. ++ priv->AdRxSignalStrength = SignalStrength; ++ } ++ ++ //printk("====>pkt rcvd by %d\n", priv->LastRxPktAntenna); ++ if( priv->LastRxPktAntenna ) //Main antenna. ++ priv->AdMainAntennaRxOkCnt++; ++ else // Aux antenna. ++ priv->AdAuxAntennaRxOkCnt++; ++ //printk("-SwAntennaDiversityRxOk8185: AdRxOkCnt: %d AdRxSignalStrength: %d\n", priv->AdRxOkCnt, priv->AdRxSignalStrength); ++} ++ ++// ++// Description: Change Antenna Switch. ++// ++bool ++SetAntenna8185( ++ struct net_device *dev, ++ u8 u1bAntennaIndex ++ ) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ bool bAntennaSwitched = false; ++ ++// printk("+SetAntenna8185(): Antenna is switching to: %d \n", u1bAntennaIndex); ++ ++ switch(u1bAntennaIndex) ++ { ++ case 0://main antenna ++ switch(priv->rf_chip) ++ { ++ case RF_ZEBRA: ++ case RF_ZEBRA2: ++ //case RF_ZEBRA4: ++ // Tx Antenna. ++ write_nic_byte(dev, ANTSEL, 0x03); // Config TX antenna. ++ ++ //PlatformEFIOWrite4Byte(Adapter, BBAddr, 0x01009b90); // Config CCK RX antenna. ++ //PlatformEFIOWrite4Byte(Adapter, BBAddr, 0x5c8D); // Config OFDM RX antenna. ++ ++ // Rx CCK . ++ write_nic_byte(dev, 0x7f, ((0x01009b90 & 0xff000000) >> 24)); ++ write_nic_byte(dev, 0x7e, ((0x01009b90 & 0x00ff0000) >> 16)); ++ write_nic_byte(dev, 0x7d, ((0x01009b90 & 0x0000ff00) >> 8)); ++ write_nic_byte(dev, 0x7c, ((0x01009b90 & 0x000000ff) >> 0)); ++ ++ // Rx OFDM. ++ write_nic_byte(dev, 0x7f, ((0x00005c8D & 0xff000000) >> 24)); ++ write_nic_byte(dev, 0x7e, ((0x00005c8D & 0x00ff0000) >> 16)); ++ write_nic_byte(dev, 0x7d, ((0x00005c8D & 0x0000ff00) >> 8)); ++ write_nic_byte(dev, 0x7c, ((0x00005c8D & 0x000000ff) >> 0)); ++ ++ bAntennaSwitched = true; ++ break; ++ ++ default: ++ printk("SetAntenna8185: unkown RFChipID(%d)\n", priv->rf_chip); ++ break; ++ } ++ break; ++ ++ case 1: ++ switch(priv->rf_chip) ++ { ++ case RF_ZEBRA: ++ case RF_ZEBRA2: ++ //case RF_ZEBRA4: ++ // Tx Antenna. ++ write_nic_byte(dev, ANTSEL, 0x00); // Config TX antenna. ++ ++ //PlatformEFIOWrite4Byte(Adapter, BBAddr, 0x0100bb90); // Config CCK RX antenna. ++ //PlatformEFIOWrite4Byte(Adapter, BBAddr, 0x548D); // Config OFDM RX antenna. ++ ++ // Rx CCK. ++ write_nic_byte(dev, 0x7f, ((0x0100bb90 & 0xff000000) >> 24)); ++ write_nic_byte(dev, 0x7e, ((0x0100bb90 & 0x00ff0000) >> 16)); ++ write_nic_byte(dev, 0x7d, ((0x0100bb90 & 0x0000ff00) >> 8)); ++ write_nic_byte(dev, 0x7c, ((0x0100bb90 & 0x000000ff) >> 0)); ++ ++ // Rx OFDM. ++ write_nic_byte(dev, 0x7f, ((0x0000548D & 0xff000000) >> 24)); ++ write_nic_byte(dev, 0x7e, ((0x0000548D & 0x00ff0000) >> 16)); ++ write_nic_byte(dev, 0x7d, ((0x0000548D & 0x0000ff00) >> 8)); ++ write_nic_byte(dev, 0x7c, ((0x0000548D & 0x000000ff) >> 0)); ++ ++ bAntennaSwitched = true; ++ break; ++ ++ default: ++ printk("SetAntenna8185: unkown RFChipID(%d)\n", priv->rf_chip); ++ break; ++ } ++ break; ++ ++ default: ++ printk("SetAntenna8185: unkown u1bAntennaIndex(%d)\n", u1bAntennaIndex); ++ break; ++ } ++ ++ if(bAntennaSwitched) ++ { ++ priv->CurrAntennaIndex = u1bAntennaIndex; ++ } ++ ++// printk("-SetAntenna8185(): return (%#X)\n", bAntennaSwitched); ++ ++ return bAntennaSwitched; ++} ++ ++// ++// Description: Toggle Antenna switch. ++// ++bool SwitchAntenna(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ ++ bool bResult = false; ++ ++ if(priv->CurrAntennaIndex == 0) ++ { ++ bResult = SetAntenna8185(dev, 1); ++ if(priv->ieee80211->state == IEEE80211_LINKED) ++ printk("Switching to Aux antenna 1 \n"); ++ } ++ else ++ { ++ bResult = SetAntenna8185(dev, 0); ++ if(priv->ieee80211->state == IEEE80211_LINKED) ++ printk("Switching to Main antenna 0 \n"); ++ } ++ ++ return bResult; ++} ++ ++// ++// Description: ++// Engine of SW Antenna Diversity mechanism. ++// Since 8187 has no Tx part information, ++// this implementation is only dependend on Rx part information. ++// ++// 2006.04.17, by rcnjko. ++// ++void SwAntennaDiversity(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ //bool bSwCheckSS=false; ++ bool bSwCheckSS=true;//open the SignalStrength check if not switched by rx ok pkt. ++ ++// printk("+SwAntennaDiversity(): CurrAntennaIndex: %d\n", priv->CurrAntennaIndex); ++ ++//by amy 080312 ++ if(bSwCheckSS){ ++ priv->AdTickCount++; ++ ++ //printk("(1) AdTickCount: %d, AdCheckPeriod: %d\n", priv->AdTickCount, priv->AdCheckPeriod); ++ //printk("(2) AdRxSignalStrength: %ld, AdRxSsThreshold: %ld\n", priv->AdRxSignalStrength, priv->AdRxSsThreshold); ++ } ++// priv->AdTickCount++;//-by amy 080312 ++ ++ // Case 1. No Link. ++ if(priv->ieee80211->state != IEEE80211_LINKED){ ++ //printk("SwAntennaDiversity(): Case 1. No Link.\n"); ++ ++ priv->bAdSwitchedChecking = false; ++ // I switch antenna here to prevent any one of antenna is broken before link established, 2006.04.18, by rcnjko.. ++ SwitchAntenna(dev); ++ } ++ // Case 2. Linked but no packet received. ++ else if(priv->AdRxOkCnt == 0){ ++ printk("SwAntennaDiversity(): Case 2. Linked but no packet received.\n"); ++ ++ priv->bAdSwitchedChecking = false; ++ SwitchAntenna(dev); ++ } ++ // Case 3. Evaluate last antenna switch action in case4. and undo it if necessary. ++ else if(priv->bAdSwitchedChecking == true){ ++ //printk("SwAntennaDiversity(): Case 3. Evaluate last antenna switch action.\n"); ++ ++ priv->bAdSwitchedChecking = false; ++ ++ // Adjust Rx signal strength threashold. ++ priv->AdRxSsThreshold = (priv->AdRxSignalStrength + priv->AdRxSsBeforeSwitched) / 2; ++ ++ priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ? ++ priv->AdMaxRxSsThreshold: priv->AdRxSsThreshold; ++ if(priv->AdRxSignalStrength < priv->AdRxSsBeforeSwitched){ ++ // Rx signal strength is not improved after we swtiched antenna. => Swich back. ++ printk("SwAntennaDiversity(): Rx Signal Strength is not improved, CurrRxSs: %ld, LastRxSs: %ld\n", priv->AdRxSignalStrength, priv->AdRxSsBeforeSwitched); ++ ++ //by amy 080312 ++ // Increase Antenna Diversity checking period due to bad decision. ++ priv->AdCheckPeriod *= 2; ++ //by amy 080312 ++ // ++ // Increase Antenna Diversity checking period. ++ if(priv->AdCheckPeriod > priv->AdMaxCheckPeriod) ++ priv->AdCheckPeriod = priv->AdMaxCheckPeriod; ++ ++ // Wrong deceision => switch back. ++ SwitchAntenna(dev); ++ }else{ // Rx Signal Strength is improved. ++ printk("SwAntennaDiversity(): Rx Signal Strength is improved, CurrRxSs: %ld, LastRxSs: %ld\n", priv->AdRxSignalStrength, priv->AdRxSsBeforeSwitched); ++ ++ // Reset Antenna Diversity checking period to its min value. ++ priv->AdCheckPeriod = priv->AdMinCheckPeriod; ++ } ++ ++ //printk("SwAntennaDiversity(): AdRxSsThreshold: %ld, AdCheckPeriod: %d\n", ++ // priv->AdRxSsThreshold, priv->AdCheckPeriod); ++ } ++ // Case 4. Evaluate if we shall switch antenna now. ++ // Cause Table Speed is very fast in TRC Dell Lab, we check it every time. ++ else// if(priv->AdTickCount >= priv->AdCheckPeriod)//-by amy 080312 ++ { ++ //printk("SwAntennaDiversity(): Case 4. Evaluate if we shall switch antenna now.\n"); ++ ++ priv->AdTickCount = 0; ++ ++ // ++ // We evaluate RxOk counts for each antenna first and than ++ // evaluate signal strength. ++ // The following operation can overcome the disability of CCA on both two antennas ++ // When signal strength was extremely low or high. ++ // 2008.01.30. ++ // ++ ++ // ++ // Evaluate RxOk count from each antenna if we shall switch default antenna now. ++ // Added by Roger, 2008.02.21. ++ ++ //{by amy 080312 ++ if((priv->AdMainAntennaRxOkCnt < priv->AdAuxAntennaRxOkCnt) && (priv->CurrAntennaIndex == 0)){ ++ // We set Main antenna as default but RxOk count was less than Aux ones. ++ ++ printk("SwAntennaDiversity(): Main antenna %d RxOK is poor, AdMainAntennaRxOkCnt: %d, AdAuxAntennaRxOkCnt: %d\n",priv->CurrAntennaIndex, priv->AdMainAntennaRxOkCnt, priv->AdAuxAntennaRxOkCnt); ++ ++ // Switch to Aux antenna. ++ SwitchAntenna(dev); ++ priv->bHWAdSwitched = true; ++ }else if((priv->AdAuxAntennaRxOkCnt < priv->AdMainAntennaRxOkCnt) && (priv->CurrAntennaIndex == 1)){ ++ // We set Aux antenna as default but RxOk count was less than Main ones. ++ ++ printk("SwAntennaDiversity(): Aux antenna %d RxOK is poor, AdMainAntennaRxOkCnt: %d, AdAuxAntennaRxOkCnt: %d\n",priv->CurrAntennaIndex, priv->AdMainAntennaRxOkCnt, priv->AdAuxAntennaRxOkCnt); ++ ++ // Switch to Main antenna. ++ SwitchAntenna(dev); ++ priv->bHWAdSwitched = true; ++ }else{// Default antenna is better. ++ ++ printk("SwAntennaDiversity(): Current Antenna %d is better., AdMainAntennaRxOkCnt: %d, AdAuxAntennaRxOkCnt: %d\n",priv->CurrAntennaIndex, priv->AdMainAntennaRxOkCnt, priv->AdAuxAntennaRxOkCnt); ++ ++ // Still need to check current signal strength. ++ priv->bHWAdSwitched = false; ++ } ++ // ++ // We evaluate Rx signal strength ONLY when default antenna ++ // didn't changed by HW evaluation. ++ // 2008.02.27. ++ // ++ // [TRC Dell Lab] SignalStrength is inaccuracy. Isaiah 2008-03-05 ++ // For example, Throughput of aux is better than main antenna(about 10M v.s 2M), ++ // but AdRxSignalStrength is less than main. ++ // Our guess is that main antenna have lower throughput and get many change ++ // to receive more CCK packets(ex.Beacon) which have stronger SignalStrength. ++ // ++ if( (!priv->bHWAdSwitched) && (bSwCheckSS)){ ++ //by amy 080312} ++ ++ // Evaluate Rx signal strength if we shall switch antenna now. ++ if(priv->AdRxSignalStrength < priv->AdRxSsThreshold){ ++ // Rx signal strength is weak => Switch Antenna. ++ printk("SwAntennaDiversity(): Rx Signal Strength is weak, CurrRxSs: %ld, RxSsThreshold: %ld\n", priv->AdRxSignalStrength, priv->AdRxSsThreshold); ++ ++ priv->AdRxSsBeforeSwitched = priv->AdRxSignalStrength; ++ priv->bAdSwitchedChecking = true; ++ ++ SwitchAntenna(dev); ++ }else{ // Rx signal strength is OK. ++ printk("SwAntennaDiversity(): Rx Signal Strength is OK, CurrRxSs: %ld, RxSsThreshold: %ld\n", priv->AdRxSignalStrength, priv->AdRxSsThreshold); ++ ++ priv->bAdSwitchedChecking = false; ++ // Increase Rx signal strength threashold if necessary. ++ if( (priv->AdRxSignalStrength > (priv->AdRxSsThreshold + 10)) && // Signal is much stronger than current threshold ++ priv->AdRxSsThreshold <= priv->AdMaxRxSsThreshold) // Current threhold is not yet reach upper limit. ++ { ++ priv->AdRxSsThreshold = (priv->AdRxSsThreshold + priv->AdRxSignalStrength) / 2; ++ priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ? ++ priv->AdMaxRxSsThreshold: priv->AdRxSsThreshold;//+by amy 080312 ++ } ++ ++ // Reduce Antenna Diversity checking period if possible. ++ if( priv->AdCheckPeriod > priv->AdMinCheckPeriod ) ++ { ++ priv->AdCheckPeriod /= 2; ++ } ++ } ++ } ++ } ++//by amy 080312 ++ // Reset antenna diversity Rx related statistics. ++ priv->AdRxOkCnt = 0; ++ priv->AdMainAntennaRxOkCnt = 0; ++ priv->AdAuxAntennaRxOkCnt = 0; ++//by amy 080312 ++ ++// priv->AdRxOkCnt = 0;//-by amy 080312 ++ ++ //printk("-SwAntennaDiversity()\n"); ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void SwAntennaWorkItemCallback(struct work_struct *work) ++{ ++ struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, SwAntennaWorkItem.work); ++ struct net_device *dev = ieee->dev; ++#else ++void SwAntennaWorkItemCallback(struct net_device *dev) ++{ ++#endif ++ //printk("==>%s \n", __func__); ++ SwAntennaDiversity(dev); ++} ++ ++// ++// Description: Timer callback function of SW Antenna Diversity. ++// ++void SwAntennaDiversityTimerCallback(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ RT_RF_POWER_STATE rtState; ++ ++ //printk("+SwAntennaDiversityTimerCallback()\n"); ++ ++ // ++ // We do NOT need to switch antenna while RF is off. ++ // 2007.05.09, added by Roger. ++ // ++ rtState = priv->eRFPowerState; ++ do{ ++ if (rtState == eRfOff){ ++// printk("SwAntennaDiversityTimer - RF is OFF.\n"); ++ break; ++ }else if (rtState == eRfSleep){ ++ // Don't access BB/RF under Disable PLL situation. ++ //RT_TRACE((COMP_RF|COMP_ANTENNA), DBG_LOUD, ("SwAntennaDiversityTimerCallback(): RF is Sleep => skip it\n")); ++ break; ++ } ++ ++ queue_work(priv->ieee80211->wq,(void *)&priv->ieee80211->SwAntennaWorkItem); ++ ++ }while(false); ++ ++ if(priv->up){ ++ //priv->SwAntennaDiversityTimer.expires = jiffies + MSECS(ANTENNA_DIVERSITY_TIMER_PERIOD); ++ //add_timer(&priv->SwAntennaDiversityTimer); ++ mod_timer(&priv->SwAntennaDiversityTimer, jiffies + MSECS(ANTENNA_DIVERSITY_TIMER_PERIOD)); ++ } ++ ++} ++#endif ++ ++ ++ +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_dm.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_dm.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_dm.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_dm.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,38 @@ ++/* ++ Hardware dynamic mechanism for RTL8187B. ++Notes: ++ This file is ported from RTL8187B Windows driver ++*/ ++ ++#ifndef R8180_DM_H ++#define R8180_DM_H ++ ++#include "r8187.h" ++ ++bool CheckDig(struct net_device *dev); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void rtl8180_hw_dig_wq (struct work_struct *work); ++#else ++void rtl8180_hw_dig_wq(struct net_device *dev); ++#endif ++ ++bool CheckHighPower(struct net_device *dev); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void rtl8180_tx_pw_wq (struct work_struct *work); ++#else ++void rtl8180_tx_pw_wq(struct net_device *dev); ++#endif ++ ++//by lzm for antenna ++#ifdef SW_ANTE_DIVERSITY ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void SwAntennaWorkItemCallback(struct work_struct *work); ++#else ++void SwAntennaWorkItemCallback(struct net_device *dev); ++#endif ++void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength); ++void SwAntennaDiversityTimerCallback(struct net_device *dev); ++#endif ++//by lzm for antenna ++ ++#endif //R8180_PM_H +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_hw.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_hw.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_hw.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_hw.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,788 @@ ++/* ++ This is part of rtl8187 OpenSource driver. ++ Copyright (C) Andrea Merello 2004-2005 ++ Released under the terms of GPL (General Public Licence) ++ ++ Parts of this driver are based on the GPL part of the ++ official Realtek driver. ++ Parts of this driver are based on the rtl8180 driver skeleton ++ from Patric Schenke & Andres Salomon. ++ Parts of this driver are based on the Intel Pro Wireless ++ 2100 GPL driver. ++ ++ We want to tanks the Authors of those projects ++ and the Ndiswrapper project Authors. ++*/ ++ ++/* Mariusz Matuszek added full registers definition with Realtek's name */ ++ ++/* this file contains register definitions for the rtl8187 MAC controller */ ++#ifndef R8180_HW ++#define R8180_HW ++ ++typedef enum _RF_TYPE_8187{ ++ RF_TYPE_MIN, ++ RF_ZEBRA = 5, ++ RF_ZEBRA2, // added by Annie, 2005-08-01. ++ RF_TYPE_MAX, ++}RF_TYPE_8187,*PRF_TYPE_8187; ++ ++typedef enum _VERSION_8187{ ++ // RTL8187 ++ VERSION_8187_B, // B-cut ++ VERSION_8187_D, // D-cut ++ // RTL8187B ++ VERSION_8187B_B, // B-cut ++ VERSION_8187B_D, //D-cut //added 2007-9-14 ++ VERSION_8187B_E, //E-cut //added 2007-9-14 ++}VERSION_8187,*PVERSION_8187; ++ ++//by lzm for antenna ++#ifdef SW_ANTE_DIVERSITY ++#define RF_PARAM 0x19 ++#define RF_PARAM_DIGPHY_SHIFT 0 ++#define RF_PARAM_ANTBDEFAULT_SHIFT 1 ++#define EEPROM_VERSION 0x3c ++#define EEPROM_CONFIG2 0x18 ++#define EEPROM_CS_THRESHOLD 0x2F ++#define EEPROM_RF_PARAM 0x08 ++//// BIT[8-9] is for SW Antenna Diversity. Only the value EEPROM_SW_AD_ENABLE means enable, other values are diable. ++#define EEPROM_SW_AD_MASK 0x0300 ++#define EEPROM_SW_AD_ENABLE 0x0100 ++//// BIT[10-11] determine if Antenna 1 is the Default Antenna. Only the value EEPROM_DEF_ANT_1 means TRUE, other values are FALSE. ++#define EEPROM_DEF_ANT_MASK 0x0C00 ++#define EEPROM_DEF_ANT_1 0x0400 ++ ++#define RCR_EnCS1 BIT29 // enable carrier sense method 1 ++#define RCR_EnCS2 BIT30 // enable carrier sense method 2 ++#endif ++//by lzm for antenna ++ ++#define RTL8187_RF_INDEX 0x8225 ++#define RTL8187_REQT_READ 0xc0 ++#define RTL8187_REQT_WRITE 0x40 ++#define RTL8187_REQ_GET_REGS 0x05 ++#define RTL8187_REQ_SET_REGS 0x05 ++ ++ ++ ++#define MAX_TX_URB 5 ++#define MAX_RX_URB 16 ++#define RX_URB_SIZE 0x9C4 ++ ++ ++ ++ ++ ++#define BB_ANTATTEN_CHAN14 0x0c ++#define BB_ANTENNA_B 0x40 ++ ++#define BB_HOST_BANG (1<<30) ++#define BB_HOST_BANG_EN (1<<2) ++#define BB_HOST_BANG_CLK (1<<1) ++#define BB_HOST_BANG_RW (1<<3) ++#define BB_HOST_BANG_DATA 1 ++ ++#define ANAPARAM_TXDACOFF_SHIFT 27 ++#define ANAPARAM_PWR0_MASK ((1<<30)|(1<<29)|(1<<28)) ++#define ANAPARAM_PWR0_SHIFT 28 ++#define ANAPARAM_PWR1_MASK ((1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<21)|(1<<20)) ++#define ANAPARAM_PWR1_SHIFT 20 ++ ++#define MAC0 0 ++#define MAC1 1 ++#define MAC2 2 ++#define MAC3 3 ++#define MAC4 4 ++#define MAC5 5 ++ ++#define RXFIFOCOUNT 0x10 ++#define TXFIFOCOUNT 0x12 ++#define BcnIntTime 0x74 ++#define TALLY_SEL 0xfc ++#define BQREQ 0x13 ++ ++#define CMD 0x37 ++#define CMD_RST_SHIFT 4 ++#define CMD_RESERVED_MASK ((1<<1) | (1<<5) | (1<<6) | (1<<7)) ++#define CMD_RX_ENABLE_SHIFT 3 ++#define CMD_TX_ENABLE_SHIFT 2 ++ ++#define EPROM_CMD 0x50 ++#define EPROM_CMD_RESERVED_MASK ((1<<5)|(1<<4)) ++#define EPROM_CMD_OPERATING_MODE_SHIFT 6 ++#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) ++#define EPROM_CMD_CONFIG 0x3 ++#define EPROM_CMD_NORMAL 0 ++#define EPROM_CMD_LOAD 1 ++#define EPROM_CMD_PROGRAM 2 ++#define EPROM_CS_SHIFT 3 ++#define EPROM_CK_SHIFT 2 ++#define EPROM_W_SHIFT 1 ++#define EPROM_R_SHIFT 0 ++#define CONFIG2_DMA_POLLING_MODE_SHIFT 3 ++#define INTA 0x3e ++#define INTA_TXOVERFLOW (1<<15) ++#define INTA_TIMEOUT (1<<14) ++#define INTA_BEACONTIMEOUT (1<<13) ++#define INTA_ATIM (1<<12) ++#define INTA_BEACONDESCERR (1<<11) ++#define INTA_BEACONDESCOK (1<<10) ++#define INTA_HIPRIORITYDESCERR (1<<9) ++#define INTA_HIPRIORITYDESCOK (1<<8) ++#define INTA_NORMPRIORITYDESCERR (1<<7) ++#define INTA_NORMPRIORITYDESCOK (1<<6) ++#define INTA_RXOVERFLOW (1<<5) ++#define INTA_RXDESCERR (1<<4) ++#define INTA_LOWPRIORITYDESCERR (1<<3) ++#define INTA_LOWPRIORITYDESCOK (1<<2) ++#define INTA_RXCRCERR (1<<1) ++#define INTA_RXOK (1) ++#define INTA_MASK 0x3c ++#define RXRING_ADDR 0xe4 // page 0 ++#define PGSELECT 0x5e ++#define PGSELECT_PG_SHIFT 0 ++#define RX_CONF 0x44 ++#define MAC_FILTER_MASK ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5) | \ ++(1<<12) | (1<<18) | (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23)) ++#define RX_CHECK_BSSID_SHIFT 23 ++#define ACCEPT_PWR_FRAME_SHIFT 22 ++#define ACCEPT_MNG_FRAME_SHIFT 20 ++#define ACCEPT_CTL_FRAME_SHIFT 19 ++#define ACCEPT_DATA_FRAME_SHIFT 18 ++#define ACCEPT_ICVERR_FRAME_SHIFT 12 ++#define ACCEPT_CRCERR_FRAME_SHIFT 5 ++#define ACCEPT_BCAST_FRAME_SHIFT 3 ++#define ACCEPT_MCAST_FRAME_SHIFT 2 ++#define ACCEPT_ALLMAC_FRAME_SHIFT 0 ++#define ACCEPT_NICMAC_FRAME_SHIFT 1 ++#define RX_FIFO_THRESHOLD_MASK ((1<<13) | (1<<14) | (1<<15)) ++#define RX_FIFO_THRESHOLD_SHIFT 13 ++#define RX_FIFO_THRESHOLD_128 3 ++#define RX_FIFO_THRESHOLD_256 4 ++#define RX_FIFO_THRESHOLD_512 5 ++#define RX_FIFO_THRESHOLD_1024 6 ++#define RX_FIFO_THRESHOLD_NONE 7 ++#define RX_AUTORESETPHY_SHIFT 28 ++#define EPROM_TYPE_SHIFT 6 ++#define TX_CONF 0x40 ++#define TX_CONF_HEADER_AUTOICREMENT_SHIFT 30 ++#define TX_LOOPBACK_SHIFT 17 ++#define TX_LOOPBACK_MAC 1 ++#define TX_LOOPBACK_BASEBAND 2 ++#define TX_LOOPBACK_NONE 0 ++#define TX_LOOPBACK_CONTINUE 3 ++#define TX_LOOPBACK_MASK ((1<<17)|(1<<18)) ++#define TX_LRLRETRY_SHIFT 0 ++#define R8180_MAX_RETRY 255 ++#define TX_SRLRETRY_SHIFT 8 ++#define TX_NOICV_SHIFT 19 ++#define TX_NOCRC_SHIFT 16 ++#define TX_DMA_POLLING 0xd9 ++#define TX_DMA_POLLING_BEACON_SHIFT 7 ++#define TX_DMA_POLLING_HIPRIORITY_SHIFT 6 ++#define TX_DMA_POLLING_NORMPRIORITY_SHIFT 5 ++#define TX_DMA_POLLING_LOWPRIORITY_SHIFT 4 ++#define TX_DMA_STOP_BEACON_SHIFT 3 ++#define TX_DMA_STOP_HIPRIORITY_SHIFT 2 ++#define TX_DMA_STOP_NORMPRIORITY_SHIFT 1 ++#define TX_DMA_STOP_LOWPRIORITY_SHIFT 0 ++#define TX_NORMPRIORITY_RING_ADDR 0x24 ++#define TX_HIGHPRIORITY_RING_ADDR 0x28 ++#define TX_LOWPRIORITY_RING_ADDR 0x20 ++#define MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10)) ++#define MAX_RX_DMA_2048 7 ++#define MAX_RX_DMA_1024 6 ++#define MAX_RX_DMA_SHIFT 10 ++#define INT_TIMEOUT 0x48 ++#define CONFIG3_CLKRUN_SHIFT 2 ++#define CONFIG3_ANAPARAM_W_SHIFT 6 ++#define ANAPARAM 0x54 ++#define BEACON_INTERVAL 0x70 ++#define BEACON_INTERVAL_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)| \ ++(1<<6)|(1<<7)|(1<<8)|(1<<9)) ++#define ATIM_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)| \ ++(1<<8)|(1<<9)) ++#define ATIM 0x72 ++#define EPROM_CS_SHIFT 3 ++#define EPROM_CK_SHIFT 2 ++#define PHY_DELAY 0x78 ++#define PHY_CONFIG 0x80 ++#define PHY_ADR 0x7c ++#define PHY_READ 0x7e ++#define CARRIER_SENSE_COUNTER 0x79 //byte ++#define SECURITY 0x5f ++#define SECURITY_WEP_TX_ENABLE_SHIFT 1 ++#define SECURITY_WEP_RX_ENABLE_SHIFT 0 ++#define SECURITY_ENCRYP_104 1 ++#define SECURITY_ENCRYP_SHIFT 4 ++#define SECURITY_ENCRYP_MASK ((1<<4)|(1<<5)) ++#define KEY0 0x90 ++#define CONFIG2_ANTENNA_SHIFT 6 ++#define TX_BEACON_RING_ADDR 0x4c ++#define CONFIG0_WEP40_SHIFT 7 ++#define CONFIG0_WEP104_SHIFT 6 ++#define AGCRESET_SHIFT 5 ++ ++ ++ ++/* ++ * Operational registers offsets in PCI (I/O) space. ++ * RealTek names are used. ++ */ ++ ++#define IDR0 0x0000 ++#define IDR1 0x0001 ++#define IDR2 0x0002 ++#define IDR3 0x0003 ++#define IDR4 0x0004 ++#define IDR5 0x0005 ++ ++/* 0x0006 - 0x0007 - reserved */ ++ ++#define MAR0 0x0008 ++#define MAR1 0x0009 ++#define MAR2 0x000A ++#define MAR3 0x000B ++#define MAR4 0x000C ++#define MAR5 0x000D ++#define MAR6 0x000E ++#define MAR7 0x000F ++ ++/* 0x0010 - 0x0017 - reserved */ ++ ++#define TSFTR 0x0018 ++#define TSFTR_END 0x001F ++ ++#define TLPDA 0x0020 ++#define TLPDA_END 0x0023 ++#define TNPDA 0x0024 ++#define TNPDA_END 0x0027 ++#define THPDA 0x0028 ++#define THPDA_END 0x002B ++ ++#define BRSR_8187 0x002C ++#define BRSR_8187_END 0x002D ++#define BRSR_8187B 0x0034 ++#define BRSR_8187B_END 0x0035 ++ ++#define BSSID 0x002E ++#define BSSID_END 0x0033 ++ ++/* 0x0034 - 0x0034 - reserved */ ++ ++/* 0x0038 - 0x003B - reserved */ ++ ++#define IMR 0x003C ++#define IMR_END 0x003D ++ ++#define ISR 0x003E ++#define ISR_END 0x003F ++ ++#define TCR 0x0040 ++#define TCR_END 0x0043 ++ ++#define RCR 0x0044 ++#define RCR_END 0x0047 ++ ++#define TimerInt 0x0048 ++#define TimerInt_END 0x004B ++ ++#define TBDA 0x004C ++#define TBDA_END 0x004F ++ ++#define CR9346 0x0050 ++ ++#define CONFIG0 0x0051 ++#define CONFIG1 0x0052 ++#define CONFIG2 0x0053 ++ ++#define ANA_PARAM 0x0054 ++#define ANA_PARAM_END 0x0x0057 ++ ++#define MSR 0x0058 ++ ++#define CONFIG3 0x0059 ++#define CONFIG4 0x005A ++ ++#define TESTR 0x005B ++ ++/* 0x005C - 0x005D - reserved */ ++#define TFPC_AC 0x005C ++#define PSR 0x005E ++ ++#define SCR 0x005F ++ ++/* 0x0060 - 0x006F - reserved */ ++#define ANA_PARAM2 0x0060 ++#define ANA_PARAM2_END 0x0063 ++ ++#define BcnIntv 0x0070 ++#define BcnItv_END 0x0071 ++ ++#define AtimWnd 0x0072 ++#define AtimWnd_END 0x0073 ++ ++#define BintrItv 0x0074 ++#define BintrItv_END 0x0075 ++ ++#define AtimtrItv 0x0076 ++#define AtimtrItv_END 0x0077 ++ ++#define PhyDelay 0x0078 ++ ++//#define CRCount 0x0079 ++ ++#define AckTimeOutReg 0x79 // ACK timeout register, in unit of 4 us. ++/* 0x007A - 0x007B - reserved */ ++#define BBAddr 0x007C ++ ++ ++#define PhyAddr 0x007C ++#define PhyDataW 0x007D ++#define PhyDataR 0x007E ++#define RF_Ready 0x007F ++ ++#define PhyCFG 0x0080 ++#define PhyCFG_END 0x0083 ++ ++/* following are for rtl8185 */ ++#define RFPinsOutput 0x80 ++#define RFPinsEnable 0x82 ++#define RF_TIMING 0x8c ++#define RFPinsSelect 0x84 ++#define ANAPARAM2 0x60 ++#define RF_PARA 0x88 ++#define RFPinsInput 0x86 ++#define GP_ENABLE 0x90 ++#define GPIO 0x91 ++#define HSSI_PARA 0x94 // HSS Parameter ++#define SW_CONTROL_GPIO 0x400 ++#define CCK_TXAGC 0x9d ++#define OFDM_TXAGC 0x9e ++#define ANTSEL 0x9f ++#define TXAGC_CTL_PER_PACKET_ANT_SEL 0x02 ++#define WPA_CONFIG 0xb0 ++#define TX_AGC_CTL 0x9c ++#define TX_AGC_CTL_PER_PACKET_TXAGC 0x01 ++#define TX_AGC_CTL_PERPACKET_GAIN_SHIFT 0 ++#define TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT 1 ++#define TX_AGC_CTL_FEEDBACK_ANT 2 ++#define RESP_RATE 0x34 ++#define SIFS 0xb4 ++#define DIFS 0xb5 ++#define EIFS_8187 0x35 ++#define EIFS_8187B 0x2D ++#define SLOT 0xb6 ++#define CW_VAL 0xbd ++#define CW_CONF 0xbc ++#define CW_CONF_PERPACKET_RETRY_LIMIT 0x02 ++#define CW_CONF_PERPACKET_CW 0x01 ++#define CW_CONF_PERPACKET_RETRY_SHIFT 1 ++#define CW_CONF_PERPACKET_CW_SHIFT 0 ++#define MAX_RESP_RATE_SHIFT 4 ++#define MIN_RESP_RATE_SHIFT 0 ++#define RATE_FALLBACK 0xbe ++#define RATE_FALLBACK_CTL_ENABLE 0x80 ++#define RATE_FALLBACK_CTL_AUTO_STEP0 0x00 ++ ++#define ARFR 0x1E0 // Auto Rate Fallback Register (0x1e0 ~ 0x1e2) ++#define RMS 0x1EC // Rx Max Pacetk Size (0x1ec[0:12]) ++ ++/* ++ * 0x0084 - 0x00D3 is selected to page 1 when PSEn bit (bit0, PSR) ++ * is set to 1 ++ */ ++ ++#define Wakeup0 0x0084 ++#define Wakeup0_END 0x008B ++ ++#define Wakeup1 0x008C ++#define Wakeup1_END 0x0093 ++ ++#define Wakeup2LD 0x0094 ++#define Wakeup2LD_END 0x009B ++#define Wakeup2HD 0x009C ++#define Wakeup2HD_END 0x00A3 ++ ++#define Wakeup3LD 0x00A4 ++#define Wakeup3LD_END 0x00AB ++#define Wakeup3HD 0x00AC ++#define Wakeup3HD_END 0x00B3 ++ ++#define Wakeup4LD 0x00B4 ++#define Wakeup4LD_END 0x00BB ++#define Wakeup4HD 0x00BC ++#define Wakeup4HD_END 0x00C3 ++ ++#define CRC0 0x00C4 ++#define CRC0_END 0x00C5 ++#define CRC1 0x00C6 ++#define CRC1_END 0x00C7 ++#define CRC2 0x00C8 ++#define CRC2_END 0x00C9 ++#define CRC3 0x00CA ++#define CRC3_END 0x00CB ++#define CRC4 0x00CC ++#define CRC4_END 0x00CD ++ ++/* 0x00CE - 0x00D3 - reserved */ ++ ++ ++ ++/* ++ * 0x0084 - 0x00D3 is selected to page 0 when PSEn bit (bit0, PSR) ++ * is set to 0 ++ */ ++ ++/* 0x0084 - 0x008F - reserved */ ++ ++#define DK0 0x0090 ++#define DK0_END 0x009F ++#define DK1 0x00A0 ++#define DK1_END 0x00AF ++#define DK2 0x00B0 ++#define DK2_END 0x00BF ++#define DK3 0x00C0 ++#define DK3_END 0x00CF ++ ++#define GPO 0x90 ++#define GPE 0x91 ++#define GPI 0x92 ++ ++#define RFTiming 0x008C ++#define ACM_CONTROL 0x00BF // ACM Control Registe ++#define INT_MIG 0x00E2 // Interrupt Migration (0xE2 ~ 0xE3) ++#define TID_AC_MAP 0x00E8 // TID to AC Mapping Register ++ ++#define AC_VO_PARAM 0x00F0 // AC_VO Parameters Record ++#define AC_VI_PARAM 0x00F4 // AC_VI Parameters Record ++#define AC_BE_PARAM 0x00F8 // AC_BE Parameters Record ++#define AC_BK_PARAM 0x00FC // AC_BK Parameters Record ++ ++/* 0x00D0 - 0x00D3 - reserved */ ++#define CCK_FALSE_ALARM 0x00D0 ++#define OFDM_FALSE_ALARM 0x00D2 ++ ++ ++/* 0x00D4 - 0x00D7 - reserved */ ++ ++#define CONFIG5 0x00D8 ++ ++#define TPPoll 0x00D9 ++ ++/* 0x00DA - 0x00DB - reserved */ ++ ++#define CWR 0x00DC ++#define CWR_END 0x00DD ++ ++#define RetryCTR 0x00DE ++ ++/* 0x00DF - 0x00E3 - reserved */ ++ ++#define RDSAR 0x00E4 ++#define RDSAR_END 0x00E7 ++ ++/* 0x00E8 - 0x00EF - reserved */ ++#define ANA_PARAM3 0x00EE ++ ++#define FER 0x00F0 ++#define FER_END 0x00F3 ++ ++#define FEMR 0x1D4 // Function Event Mask register (0xf4 ~ 0xf7) ++//#define FEMR 0x00F4 ++#define FEMR_END 0x00F7 ++ ++#define FPSR 0x00F8 ++#define FPSR_END 0x00FB ++ ++#define FFER 0x00FC ++#define FFER_END 0x00FF ++ ++/* ++ * 0x0000 - 0x00ff is selected to page 0 when PSEn bit (bit0, PSR) ++ * is set to 2 ++ */ ++#define RFSW_CTRL 0x272 // 0x272-0x273. ++ ++ ++ ++//---------------------------------------------------------------------------- ++// 8187B AC_XX_PARAM bits ++//---------------------------------------------------------------------------- ++#define AC_PARAM_TXOP_LIMIT_OFFSET 16 ++#define AC_PARAM_ECW_MAX_OFFSET 12 ++#define AC_PARAM_ECW_MIN_OFFSET 8 ++#define AC_PARAM_AIFS_OFFSET 0 ++ ++//---------------------------------------------------------------------------- ++// 8187B ACM_CONTROL bits (Offset 0xBF, 1 Byte) ++//---------------------------------------------------------------------------- ++#define VOQ_ACM_EN (0x01 << 7) //BIT7 ++#define VIQ_ACM_EN (0x01 << 6) //BIT6 ++#define BEQ_ACM_EN (0x01 << 5) //BIT5 ++#define ACM_HW_EN (0x01 << 4) //BIT4 ++#define TXOPSEL (0x01 << 3) //BIT3 ++#define VOQ_ACM_CTL (0x01 << 2) //BIT2 // Set to 1 when AC_VO used time reaches or exceeds the admitted time ++#define VIQ_ACM_CTL (0x01 << 1) //BIT1 // Set to 1 when AC_VI used time reaches or exceeds the admitted time ++#define BEQ_ACM_CTL (0x01 << 0) //BIT0 // Set to 1 when AC_BE used time reaches or exceeds the admitted time ++ ++//---------------------------------------------------------------------------- ++// 8187B RF pins related setting (offset 0xFF80-0xFF87,) ++//---------------------------------------------------------------------------- ++#define TR_SW_MASK_TX_8187 BIT5 ++#define TR_SW_MASK_RX_8187 BIT6 ++#define TR_SW_MASK_8187 (TR_SW_MASK_TX_8187 | TR_SW_MASK_RX_8187) ++ ++/* ++ * Bitmasks for specific register functions. ++ * Names are derived from the register name and function name. ++ * ++ * _[] ++ * ++ * this leads to some awkward names... ++ */ ++ ++#define BRSR_BPLCP ((1<< 8)) ++#define BRSR_MBR ((1<< 1)|(1<< 0)) ++#define BRSR_MBR_8185 ((1<< 11)|(1<< 10)|(1<< 9)|(1<< 8)|(1<< 7)|(1<< 6)|(1<< 5)|(1<< 4)|(1<< 3)|(1<< 2)|(1<< 1)|(1<< 0)) ++#define BRSR_MBR0 ((1<< 0)) ++#define BRSR_MBR1 ((1<< 1)) ++ ++#define CR_RST ((1<< 4)) ++#define CR_RE ((1<< 3)) ++#define CR_TE ((1<< 2)) ++#define CR_MulRW ((1<< 0)) ++ ++#define IMR_TXFOVW ((1<<15)) ++#define IMR_TimeOut ((1<<14)) ++#define IMR_BcnInt ((1<<13)) ++#define IMR_ATIMInt ((1<<12)) ++#define IMR_TBDER ((1<<11)) ++#define IMR_TBDOK ((1<<10)) ++#define IMR_THPDER ((1<< 9)) ++#define IMR_THPDOK ((1<< 8)) ++#define IMR_TNPDER ((1<< 7)) ++#define IMR_TNPDOK ((1<< 6)) ++#define IMR_RXFOVW ((1<< 5)) ++#define IMR_RDU ((1<< 4)) ++#define IMR_TLPDER ((1<< 3)) ++#define IMR_TLPDOK ((1<< 2)) ++#define IMR_RER ((1<< 1)) ++#define IMR_ROK ((1<< 0)) ++ ++#define ISR_TXFOVW ((1<<15)) ++#define ISR_TimeOut ((1<<14)) ++#define ISR_BcnInt ((1<<13)) ++#define ISR_ATIMInt ((1<<12)) ++#define ISR_TBDER ((1<<11)) ++#define ISR_TBDOK ((1<<10)) ++#define ISR_THPDER ((1<< 9)) ++#define ISR_THPDOK ((1<< 8)) ++#define ISR_TNPDER ((1<< 7)) ++#define ISR_TNPDOK ((1<< 6)) ++#define ISR_RXFOVW ((1<< 5)) ++#define ISR_RDU ((1<< 4)) ++#define ISR_TLPDER ((1<< 3)) ++#define ISR_TLPDOK ((1<< 2)) ++#define ISR_RER ((1<< 1)) ++#define ISR_ROK ((1<< 0)) ++ ++#define HW_VERID_R8180_F 3 ++#define HW_VERID_R8180_ABCD 2 ++#define HW_VERID_R8185_ABC 4 ++#define HW_VERID_R8185_D 5 ++ ++#define TCR_DurProcMode ((1<<30)) ++#define TCR_DISReqQsize ((1<<28)) ++#define TCR_HWVERID_MASK ((1<<27)|(1<<26)|(1<<25)) ++#define TCR_HWVERID_SHIFT 25 ++#define TCR_SWPLCPLEN ((1<<24)) ++#define TCR_PLCP_LEN TCR_SAT // rtl8180 ++#define TCR_MXDMA_MASK ((1<<23)|(1<<22)|(1<<21)) ++#define TCR_MXDMA_1024 6 ++#define TCR_MXDMA_2048 7 ++#define TCR_MXDMA_SHIFT 21 ++#define TCR_DISCW ((1<<20)) ++#define TCR_ICV ((1<<19)) ++#define TCR_LBK ((1<<18)|(1<<17)) ++#define TCR_LBK1 ((1<<18)) ++#define TCR_LBK0 ((1<<17)) ++#define TCR_CRC ((1<<16)) ++#define TCR_SRL_MASK ((1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)) ++#define TCR_LRL_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)) ++#define TCR_PROBE_NOTIMESTAMP_SHIFT 29 //rtl8185 ++ ++#define RCR_ONLYERLPKT ((1<<31)) ++#define RCR_CS_SHIFT 29 ++#define RCR_CS_MASK ((1<<30) | (1<<29)) ++#define RCR_ENMARP ((1<<28)) ++#define RCR_CBSSID ((1<<23)) ++#define RCR_APWRMGT ((1<<22)) ++#define RCR_ADD3 ((1<<21)) ++#define RCR_AMF ((1<<20)) ++#define RCR_ACF ((1<<19)) ++#define RCR_ADF ((1<<18)) ++#define RCR_RXFTH ((1<<15)|(1<<14)|(1<<13)) ++#define RCR_RXFTH2 ((1<<15)) ++#define RCR_RXFTH1 ((1<<14)) ++#define RCR_RXFTH0 ((1<<13)) ++#define RCR_AICV ((1<<12)) ++#define RCR_MXDMA ((1<<10)|(1<< 9)|(1<< 8)) ++#define RCR_MXDMA2 ((1<<10)) ++#define RCR_MXDMA1 ((1<< 9)) ++#define RCR_MXDMA0 ((1<< 8)) ++#define RCR_9356SEL ((1<< 6)) ++#define RCR_ACRC32 ((1<< 5)) ++#define RCR_AB ((1<< 3)) ++#define RCR_AM ((1<< 2)) ++#define RCR_APM ((1<< 1)) ++#define RCR_AAP ((1<< 0)) ++ ++#define CR9346_EEM ((1<<7)|(1<<6)) ++#define CR9346_EEM1 ((1<<7)) ++#define CR9346_EEM0 ((1<<6)) ++#define CR9346_EECS ((1<<3)) ++#define CR9346_EESK ((1<<2)) ++#define CR9346_EED1 ((1<<1)) ++#define CR9346_EED0 ((1<<0)) ++ ++#define CONFIG0_WEP104 ((1<<6)) ++#define CONFIG0_LEDGPO_En ((1<<4)) ++#define CONFIG0_Aux_Status ((1<<3)) ++#define CONFIG0_GL ((1<<1)|(1<<0)) ++#define CONFIG0_GL1 ((1<<1)) ++#define CONFIG0_GL0 ((1<<0)) ++ ++#define CONFIG1_LEDS ((1<<7)|(1<<6)) ++#define CONFIG1_LEDS1 ((1<<7)) ++#define CONFIG1_LEDS0 ((1<<6)) ++#define CONFIG1_LWACT ((1<<4)) ++#define CONFIG1_MEMMAP ((1<<3)) ++#define CONFIG1_IOMAP ((1<<2)) ++#define CONFIG1_VPD ((1<<1)) ++#define CONFIG1_PMEn ((1<<0)) ++ ++#define CONFIG2_LCK ((1<<7)) ++#define CONFIG2_ANT ((1<<6)) ++#define CONFIG2_DPS ((1<<3)) ++#define CONFIG2_PAPE_sign ((1<<2)) ++#define CONFIG2_PAPE_time ((1<<1)|(1<<0)) ++#define CONFIG2_PAPE_time1 ((1<<1)) ++#define CONFIG2_PAPE_time0 ((1<<0)) ++ ++#define CONFIG3_GNTSel ((1<<7)) ++#define CONFIG3_PARM_En ((1<<6)) ++#define CONFIG3_Magic ((1<<5)) ++#define CONFIG3_CardB_En ((1<<3)) ++#define CONFIG3_CLKRUN_En ((1<<2)) ++#define CONFIG3_FuncRegEn ((1<<1)) ++#define CONFIG3_FBtbEn ((1<<0)) ++ ++#define CONFIG4_VCOPDN ((1<<7)) ++#define CONFIG4_PWROFF ((1<<6)) ++#define CONFIG4_PWRMGT ((1<<5)) ++#define CONFIG4_LWPME ((1<<4)) ++#define CONFIG4_LWPTN ((1<<2)) ++#define CONFIG4_RFTYPE ((1<<1)|(1<<0)) ++#define CONFIG4_RFTYPE1 ((1<<1)) ++#define CONFIG4_RFTYPE0 ((1<<0)) ++ ++#define CONFIG5_TX_FIFO_OK ((1<<7)) ++#define CONFIG5_RX_FIFO_OK ((1<<6)) ++#define CONFIG5_CALON ((1<<5)) ++#define CONFIG5_EACPI ((1<<2)) ++#define CONFIG5_LANWake ((1<<1)) ++#define CONFIG5_PME_STS ((1<<0)) ++ ++#define MSR_LINK_MASK ((1<<2)|(1<<3)) ++#define MSR_LINK_MANAGED 2 ++#define MSR_LINK_NONE 0 ++#define MSR_LINK_SHIFT 2 ++#define MSR_LINK_ADHOC 1 ++#define MSR_LINK_MASTER 3 ++#define MSR_LINK_ENEDCA (1<<4) ++ ++#define PSR_GPO ((1<<7)) ++#define PSR_GPI ((1<<6)) ++#define PSR_LEDGPO1 ((1<<5)) ++#define PSR_LEDGPO0 ((1<<4)) ++#define PSR_UWF ((1<<1)) ++#define PSR_PSEn ((1<<0)) ++ ++#define SCR_KM ((1<<5)|(1<<4)) ++#define SCR_KM1 ((1<<5)) ++#define SCR_KM0 ((1<<4)) ++#define SCR_TXSECON ((1<<1)) ++#define SCR_RXSECON ((1<<0)) ++ ++#define BcnItv_BcnItv (0x01FF) ++ ++#define AtimWnd_AtimWnd (0x01FF) ++ ++#define BintrItv_BintrItv (0x01FF) ++ ++#define AtimtrItv_AtimtrItv (0x01FF) ++ ++#define PhyDelay_PhyDelay ((1<<2)|(1<<1)|(1<<0)) ++ ++#define TPPoll_BQ ((1<<7)) ++#define TPPoll_HPQ ((1<<6)) ++#define TPPoll_NPQ ((1<<5)) ++#define TPPoll_LPQ ((1<<4)) ++#define TPPoll_SBQ ((1<<3)) ++#define TPPoll_SHPQ ((1<<2)) ++#define TPPoll_SNPQ ((1<<1)) ++#define TPPoll_SLPQ ((1<<0)) ++ ++#define CWR_CW (0x01FF) ++ ++#define FER_INTR ((1<<15)) ++#define FER_GWAKE ((1<< 4)) ++ ++#define FEMR_INTR ((1<<15)) ++#define FEMR_WKUP ((1<<14)) ++#define FEMR_GWAKE ((1<< 4)) ++ ++#define FPSR_INTR ((1<<15)) ++#define FPSR_GWAKE ((1<< 4)) ++ ++#define FFER_INTR ((1<<15)) ++#define FFER_GWAKE ((1<< 4)) ++ ++ ++//---------------------------------------------------------------------------- ++// 818xB AnaParm & AnaParm2 Register ++//---------------------------------------------------------------------------- ++/* ++#ifdef RTL8185B_FPGA ++#define ANAPARM_FPGA_ON 0xa0000b59 ++//#define ANAPARM_FPGA_OFF ++#define ANAPARM2_FPGA_ON 0x860dec11 ++//#define ANAPARM2_FPGA_OFF ++#else //ASIC ++*/ ++#define ANAPARM_ASIC_ON 0x45090658 ++//#define ANAPARM_ASIC_OFF ++#define ANAPARM2_ASIC_ON 0x727f3f52 ++//#define ANAPARM2_ASIC_OFF ++//#endif ++//by amy for power save ++#define RF_CHANGE_BY_SW BIT31 ++#define RF_CHANGE_BY_HW BIT30 ++#define RF_CHANGE_BY_PS BIT29 ++#define RF_CHANGE_BY_IPS BIT28 ++#define ANAPARM_ASIC_ON 0x45090658 ++#define ANAPARM2_ASIC_ON 0x727f3f52 ++ ++#define ANAPARM_ON ANAPARM_ASIC_ON ++#define ANAPARM2_ON ANAPARM2_ASIC_ON ++#define TFPC 0x5C // Tx FIFO Packet Count for BK, BE, VI, VO queues (2 bytes) ++#define Config4_PowerOff BIT6 // Turn ON/Off RF Power(RFMD) ++#define ANAPARM_OFF 0x51480658 ++#define ANAPARM2_OFF 0x72003f70 ++//by amy for power save ++ ++#define MAX_DOZE_WAITING_TIMES_87B 500 ++ ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_pm.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_pm.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_pm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_pm.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,99 @@ ++/* ++ Power management interface routines. ++ Written by Mariusz Matuszek. ++ This code is currently just a placeholder for later work and ++ does not do anything useful. ++ ++ This is part of rtl8180 OpenSource driver. ++ Copyright (C) Andrea Merello 2004 ++ Released under the terms of GPL (General Public Licence) ++*/ ++ ++#ifdef CONFIG_RTL8180_PM ++ ++ ++#include "r8180_hw.h" ++#include "r8180_pm.h" ++#include "r8187.h" ++int rtl8180_save_state (struct pci_dev *dev, u32 state) ++{ ++ printk(KERN_NOTICE "r8180 save state call (state %u).\n", state); ++ return(-EAGAIN); ++} ++ ++//netif_running is set to 0 before system call rtl8180_close, ++//netif_running is set to 1 before system call rtl8180_open, ++//if open success it will not change, or it change to 0; ++int rtl8187_suspend (struct usb_interface *intf, pm_message_t state) ++{ ++ struct r8180_priv *priv; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ struct net_device *dev = usb_get_intfdata(intf); ++#else ++ //struct net_device *dev = (struct net_device *)ptr; ++#endif ++ ++ printk("====>%s \n", __func__); ++ priv=ieee80211_priv(dev); ++ ++ if(dev) { ++#ifdef POLLING_METHOD_FOR_RADIO ++ del_timer_sync(&priv->gpio_polling_timer); ++ cancel_delayed_work(&priv->ieee80211->GPIOChangeRFWorkItem); ++ priv->polling_timer_on = 0; ++#endif ++ if (!netif_running(dev)) { ++ //printk(KERN_WARNING "UI or other close dev before suspend, go out suspend function\n"); ++ return 0; ++ } ++ ++ dev->netdev_ops->ndo_stop(dev); ++ netif_device_detach(dev); ++ } ++ return 0; ++} ++ ++ ++int rtl8187_resume (struct usb_interface *intf) ++{ ++ struct r8180_priv *priv; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ struct net_device *dev = usb_get_intfdata(intf); ++#else ++ //struct net_device *dev = (struct net_device *)ptr; ++#endif ++ ++ printk("====>%s \n", __func__); ++ priv=ieee80211_priv(dev); ++ ++ if(dev) { ++#ifdef POLLING_METHOD_FOR_RADIO ++ if(priv->polling_timer_on == 0){//add for S3/S4 ++ gpio_change_polling((unsigned long)dev); ++ } ++#endif ++ if (!netif_running(dev)){ ++ //printk(KERN_WARNING "UI or other close dev before suspend, go out resume function\n"); ++ return 0; ++ } ++ ++ netif_device_attach(dev); ++ dev->netdev_ops->ndo_open(dev); ++ } ++ ++ return 0; ++} ++ ++ ++int rtl8180_enable_wake (struct pci_dev *dev, u32 state, int enable) ++{ ++ ++ //printk(KERN_NOTICE "r8180 enable wake call (state %u, enable %d).\n", ++ // state, enable); ++ return 0; ++ //return(-EAGAIN); ++} ++ ++ ++ ++#endif //CONFIG_RTL8180_PM +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_pm.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_pm.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_pm.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_pm.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,28 @@ ++/* ++ Power management interface routines. ++ Written by Mariusz Matuszek. ++ This code is currently just a placeholder for later work and ++ does not do anything useful. ++ ++ This is part of rtl8180 OpenSource driver. ++ Copyright (C) Andrea Merello 2004 ++ Released under the terms of GPL (General Public Licence) ++ ++*/ ++ ++#ifdef CONFIG_RTL8180_PM ++ ++#ifndef R8180_PM_H ++#define R8180_PM_H ++ ++#include ++#include ++ ++int rtl8180_save_state (struct pci_dev *dev, u32 state); ++int rtl8187_suspend (struct usb_interface *intf,pm_message_t state); ++int rtl8187_resume (struct usb_interface *intf); ++int rtl8180_enable_wake (struct pci_dev *dev, u32 state, int enable); ++ ++#endif //R8180_PM_H ++ ++#endif // CONFIG_RTL8180_PM +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_rtl8225.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_rtl8225.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_rtl8225.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_rtl8225.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,1007 @@ ++/* ++ This is part of the rtl8180-sa2400 driver ++ released under the GPL (See file COPYING for details). ++ Copyright (c) 2005 Andrea Merello ++ ++ This files contains programming code for the rtl8225 ++ radio frontend. ++ ++ *Many* thanks to Realtek Corp. for their great support! ++ ++*/ ++ ++ ++ ++#include "r8180_hw.h" ++#include "r8180_rtl8225.h" ++#ifdef ENABLE_DOT11D ++#include "dot11d.h" ++#endif ++ ++#define USE_8051_3WIRE 1 ++ ++u8 rtl8225_threshold[]={ ++ 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd, ++}; ++ ++u8 rtl8225_gain[]={ ++ 0x23,0x88,0x7c,0xa5,// -82dbm ++ 0x23,0x88,0x7c,0xb5,// -82dbm ++ 0x23,0x88,0x7c,0xc5,// -82dbm ++ 0x33,0x80,0x79,0xc5,// -78dbm ++ 0x43,0x78,0x76,0xc5,// -74dbm ++ 0x53,0x60,0x73,0xc5,// -70dbm ++ 0x63,0x58,0x70,0xc5,// -66dbm ++}; ++ ++u16 rtl8225bcd_rxgain[]={ ++ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, ++ 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, ++ 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, ++ 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, ++ 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, ++ 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, ++ 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, ++ 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, ++ 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, ++ 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, ++ 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3, ++ 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb ++ ++}; ++ ++ ++ ++u8 rtl8225_tx_gain_cck_ofdm[]={ ++ 0x02,0x06,0x0e,0x1e,0x3e,0x7e ++}; ++ ++ ++u8 rtl8225_tx_power_ofdm[]={ ++ 0x80,0x90,0xa2,0xb5,0xcb,0xe4 ++}; ++ ++ ++u8 rtl8225_tx_power_cck_ch14[]={ ++ 0x18,0x17,0x15,0x0c,0x00,0x00,0x00,0x00, ++ 0x1b,0x1a,0x17,0x0e,0x00,0x00,0x00,0x00, ++ 0x1f,0x1e,0x1a,0x0f,0x00,0x00,0x00,0x00, ++ 0x22,0x21,0x1d,0x11,0x00,0x00,0x00,0x00, ++ 0x26,0x25,0x21,0x13,0x00,0x00,0x00,0x00, ++ 0x2b,0x2a,0x25,0x15,0x00,0x00,0x00,0x00 ++}; ++ ++ ++u8 rtl8225_tx_power_cck[]={ ++ 0x18,0x17,0x15,0x11,0x0c,0x08,0x04,0x02, ++ 0x1b,0x1a,0x17,0x13,0x0e,0x09,0x04,0x02, ++ 0x1f,0x1e,0x1a,0x15,0x10,0x0a,0x05,0x02, ++ 0x22,0x21,0x1d,0x18,0x11,0x0b,0x06,0x02, ++ 0x26,0x25,0x21,0x1b,0x14,0x0d,0x06,0x03, ++ 0x2b,0x2a,0x25,0x1e,0x16,0x0e,0x07,0x03 ++}; ++ ++u8 rtl8225_agc[]={ ++ 0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9d,0x9c,0x9b,0x9a,0x99,0x98,0x97,0x96, ++ 0x95,0x94,0x93,0x92,0x91,0x90,0x8f,0x8e,0x8d,0x8c,0x8b,0x8a,0x89,0x88,0x87,0x86, ++ 0x85,0x84,0x83,0x82,0x81,0x80,0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x37,0x36, ++ 0x35,0x34,0x33,0x32,0x31,0x30,0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,0x27,0x26, ++ 0x25,0x24,0x23,0x22,0x21,0x20,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16, ++ 0x15,0x14,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06, ++ 0x05,0x04,0x03,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, ++ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, ++}; ++ ++u32 rtl8225_chan[] = { ++ 0, //dummy channel 0 ++ 0x085c, //1 ++ 0x08dc, //2 ++ 0x095c, //3 ++ 0x09dc, //4 ++ 0x0a5c, //5 ++ 0x0adc, //6 ++ 0x0b5c, //7 ++ 0x0bdc, //8 ++ 0x0c5c, //9 ++ 0x0cdc, //10 ++ 0x0d5c, //11 ++ 0x0ddc, //12 ++ 0x0e5c, //13 ++ //0x0f5c, //14 ++ 0x0f72, // 14 ++}; ++ ++void rtl8225_set_gain(struct net_device *dev, short gain) ++{ ++ write_phy_ofdm(dev, 0x0d, rtl8225_gain[gain * 4]); ++ write_phy_ofdm(dev, 0x1b, rtl8225_gain[gain * 4 + 2]); ++ write_phy_ofdm(dev, 0x1d, rtl8225_gain[gain * 4 + 3]); ++ write_phy_ofdm(dev, 0x23, rtl8225_gain[gain * 4 + 1]); ++ ++} ++ ++ ++void write_rtl8225(struct net_device *dev, u8 adr, u16 data) ++{ ++//in windows the delays in this function was del from 85 to 87, ++//here we mod to sleep, or The CPU occupany is too hight. LZM 31/10/2008 ++ ++#ifdef USE_8051_3WIRE ++ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ //u8 bit; ++ //u16 wReg80, wReg82, wReg84; ++ u16 wReg80, wReg84; ++ ++ wReg80 = read_nic_word(dev, RFPinsOutput); ++ wReg80 &= 0xfff3; ++// wReg82 = read_nic_word(dev, RFPinsEnable); ++ wReg84 = read_nic_word(dev, RFPinsSelect); ++ // 3-wire should be controled by HW when we finish SW 3-wire programming. 2005.08.10, by rcnjko. ++ //wReg84 &= 0xfff0; ++ wReg84 &= 0xfff8; //modified by david according to windows segment code. ++ ++ // We must set SW enabled before terminating HW 3-wire, 2005.07.29, by rcnjko. ++// write_nic_word(dev, RFPinsEnable, (wReg82|0x0007)); // Set To Output Enable ++ write_nic_word(dev, RFPinsSelect, (wReg84|0x0007)); // Set To SW Switch ++// force_pci_posting(dev); ++// udelay(10); // ++ ++ write_nic_word(dev, 0x80, (BB_HOST_BANG_EN|wReg80)); // Set SI_EN (RFLE) ++// force_pci_posting(dev); ++// udelay(2); ++ //twreg.struc.enableB = 0; ++ write_nic_word(dev, 0x80, (wReg80)); // Clear SI_EN (RFLE) ++// force_pci_posting(dev); ++// udelay(10); ++ ++ usb_control_msg(udev, usb_sndctrlpipe(udev, 0), ++ RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, ++ adr, 0x8225, &data, 2, HZ / 2); ++ ++ // write_nic_word(dev, 0x80, (BB_HOST_BANG_EN|wReg80)); ++// force_pci_posting(dev); ++// udelay(10); ++ ++ write_nic_word(dev, 0x80, (wReg80|0x0004)); ++ write_nic_word(dev, 0x84, (wReg84|0x0000));// Set To SW Switch ++ ++ if(priv->card_type == USB) ++ ;// msleep(2); ++ else ++ ; // rtl8185_rf_pins_enable(dev); ++ ++#else ++ int i; ++ u16 out,select; ++ u8 bit; ++ u32 bangdata = (data << 4) | (adr & 0xf); ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ out = read_nic_word(dev, RFPinsOutput) & 0xfff3; ++ ++ write_nic_word(dev,RFPinsEnable, ++ (read_nic_word(dev,RFPinsEnable) | 0x7)); ++ ++ select = read_nic_word(dev, RFPinsSelect); ++ ++ write_nic_word(dev, RFPinsSelect, select | 0x7 | ++ ((priv->card_type == USB) ? 0 : SW_CONTROL_GPIO)); ++ ++// force_pci_posting(dev); ++// udelay(10); ++ ++ write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN );//| 0x1fff); ++ ++// force_pci_posting(dev); ++// udelay(2); ++ ++ write_nic_word(dev, RFPinsOutput, out); ++ ++// force_pci_posting(dev); ++// udelay(10); ++ ++ ++ for(i=15; i>=0;i--){ ++ ++ bit = (bangdata & (1<> i; ++ ++ write_nic_word(dev, RFPinsOutput, bit | out); ++ ++ write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); ++ write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); ++ ++ i--; ++ bit = (bangdata & (1<> i; ++ ++ write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); ++ write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); ++ ++ write_nic_word(dev, RFPinsOutput, bit | out); ++ ++ } ++ ++ write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN); ++ ++// force_pci_posting(dev); ++// udelay(10); ++ ++ write_nic_word(dev, RFPinsOutput, out | ++ ((priv->card_type == USB) ? 4 : BB_HOST_BANG_EN)); ++ ++ write_nic_word(dev, RFPinsSelect, select | ++ ((priv->card_type == USB) ? 0 : SW_CONTROL_GPIO)); ++ ++ if(priv->card_type == USB) ++ ;// msleep(2); ++ else ++// rtl8185_rf_pins_enable(dev); ++#endif ++} ++ ++ ++void write_rtl8225_patch(struct net_device *dev, u8 adr, u16 data) ++{ ++ ++ int i; ++ u16 out,select; ++ u8 bit; ++ u32 bangdata = (data << 4) | (adr & 0xf); ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ out = read_nic_word(dev, RFPinsOutput) & 0xfff3; ++ ++ write_nic_word(dev,RFPinsEnable, ++ (read_nic_word(dev,RFPinsEnable) | 0x7)); ++ ++ select = read_nic_word(dev, RFPinsSelect); ++ ++ write_nic_word(dev, RFPinsSelect, select | 0x7 | ++ ((priv->card_type == USB) ? 0 : SW_CONTROL_GPIO)); ++ ++ force_pci_posting(dev); ++ udelay(10); ++ ++ write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN );//| 0x1fff); ++ ++ force_pci_posting(dev); ++ udelay(2); ++ ++ write_nic_word(dev, RFPinsOutput, out); ++ ++ force_pci_posting(dev); ++ udelay(10); ++ ++ for(i=15; i>=0;i--){ ++ ++ bit = (bangdata & (1<> i; ++ ++ write_nic_word(dev, RFPinsOutput, bit | out); ++ ++ write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); ++ write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); ++ ++ i--; ++ bit = (bangdata & (1<> i; ++ ++ write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); ++ write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); ++ ++ write_nic_word(dev, RFPinsOutput, bit | out); ++ ++ } ++ ++ write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN); ++ ++ force_pci_posting(dev); ++ udelay(10); ++ ++ write_nic_word(dev, RFPinsOutput, out | ++ ((priv->card_type == USB) ? 4 : BB_HOST_BANG_EN)); ++ ++ write_nic_word(dev, RFPinsSelect, select | ++ ((priv->card_type == USB) ? 0 : SW_CONTROL_GPIO)); ++ ++ if(priv->card_type == USB) ++ mdelay(2); ++ else ++ rtl8185_rf_pins_enable(dev); ++ ++} ++ ++void rtl8225_rf_close(struct net_device *dev) ++{ ++ write_rtl8225(dev, 0x4, 0x1f); ++ ++ force_pci_posting(dev); ++ mdelay(1); ++ ++ rtl8180_set_anaparam(dev, RTL8225_ANAPARAM_OFF); ++ rtl8185_set_anaparam2(dev, RTL8225_ANAPARAM2_OFF); ++} ++ ++#ifdef ENABLE_DOT11D ++// ++// Description: ++// Map dBm into Tx power index according to ++// current HW model, for example, RF and PA, and ++// current wireless mode. ++// ++s8 ++DbmToTxPwrIdx( ++ struct r8180_priv *priv, ++ WIRELESS_MODE WirelessMode, ++ s32 PowerInDbm ++ ) ++{ ++ bool bUseDefault = true; ++ s8 TxPwrIdx = 0; ++ ++#ifdef CONFIG_RTL818X_S ++ // ++ // 071011, SD3 SY: ++ // OFDM Power in dBm = Index * 0.5 + 0 ++ // CCK Power in dBm = Index * 0.25 + 13 ++ // ++ if(priv->card_8185 >= VERSION_8187S_B) ++ { ++ s32 tmp = 0; ++ ++ if(WirelessMode == WIRELESS_MODE_G) ++ { ++ bUseDefault = false; ++ tmp = (2 * PowerInDbm); ++ ++ if(tmp < 0) ++ TxPwrIdx = 0; ++ else if(tmp > 40) // 40 means 20 dBm. ++ TxPwrIdx = 40; ++ else ++ TxPwrIdx = (s8)tmp; ++ } ++ else if(WirelessMode == WIRELESS_MODE_B) ++ { ++ bUseDefault = false; ++ tmp = (4 * PowerInDbm) - 52; ++ ++ if(tmp < 0) ++ TxPwrIdx = 0; ++ else if(tmp > 28) // 28 means 20 dBm. ++ TxPwrIdx = 28; ++ else ++ TxPwrIdx = (s8)tmp; ++ } ++ } ++#endif ++ ++ // ++ // TRUE if we want to use a default implementation. ++ // We shall set it to FALSE when we have exact translation formular ++ // for target IC. 070622, by rcnjko. ++ // ++ if(bUseDefault) ++ { ++ if(PowerInDbm < 0) ++ TxPwrIdx = 0; ++ else if(PowerInDbm > 35) ++ TxPwrIdx = 35; ++ else ++ TxPwrIdx = (u8)PowerInDbm; ++ } ++ ++ return TxPwrIdx; ++} ++#endif ++ ++ ++short rtl8225_rf_set_sens(struct net_device *dev, short sens) ++{ ++ if (sens <0 || sens > 6) return -1; ++ ++ if(sens > 4) ++ write_rtl8225(dev, 0x0c, 0x850); ++ else ++ write_rtl8225(dev, 0x0c, 0x50); ++ ++ sens= 6-sens; ++ rtl8225_set_gain(dev, sens); ++ ++ write_phy_cck(dev, 0x41, rtl8225_threshold[sens]); ++ return 0; ++ ++} ++ ++void rtl8225_SetTXPowerLevel(struct net_device *dev, short ch) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ int GainIdx; ++ int GainSetting; ++ int i; ++ u8 power; ++ u8 *cck_power_table; ++ u8 max_cck_power_level; ++ u8 max_ofdm_power_level; ++ u8 min_ofdm_power_level; ++ u8 cck_power_level = 0xff & priv->chtxpwr[ch]; ++ u8 ofdm_power_level = 0xff & priv->chtxpwr_ofdm[ch]; ++ ++#ifdef ENABLE_DOT11D ++ if(IS_DOT11D_ENABLE(priv->ieee80211) && ++ IS_DOT11D_STATE_DONE(priv->ieee80211) ) ++ { ++ //PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(priv->ieee80211); ++ u8 MaxTxPwrInDbm = DOT11D_GetMaxTxPwrInDbm(priv->ieee80211, ch); ++ u8 CckMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_B, MaxTxPwrInDbm); ++ u8 OfdmMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_G, MaxTxPwrInDbm); ++ ++ //printk("Max Tx Power dBm (%d) => CCK Tx power index : %d, OFDM Tx power index: %d\n", MaxTxPwrInDbm, CckMaxPwrIdx, OfdmMaxPwrIdx); ++ ++ //printk("EEPROM channel(%d) => CCK Tx power index: %d, OFDM Tx power index: %d\n", ++ // ch, cck_power_level, ofdm_power_level); ++ ++ if(cck_power_level > CckMaxPwrIdx) ++ cck_power_level = CckMaxPwrIdx; ++ if(ofdm_power_level > OfdmMaxPwrIdx) ++ ofdm_power_level = OfdmMaxPwrIdx; ++ } ++ ++ //priv->CurrentCckTxPwrIdx = cck_power_level; ++ //priv->CurrentOfdmTxPwrIdx = ofdm_power_level; ++#endif ++ ++ ++ if(priv->card_type == USB){ ++ max_cck_power_level = 11; ++ max_ofdm_power_level = 25; // 12 -> 25 ++ min_ofdm_power_level = 10; ++ }else{ ++ max_cck_power_level = 35; ++ max_ofdm_power_level = 35; ++ min_ofdm_power_level = 0; ++ } ++ if( priv->TrSwitchState == TR_SW_TX ) ++ { ++ printk("SetTxPowerLevel8187(): Origianl OFDM Tx power level %d\n", ofdm_power_level); ++ ofdm_power_level -= GetTxOfdmHighPowerBias(dev); ++ cck_power_level -= GetTxCckHighPowerBias(dev); ++ printk("SetTxPowerLevel8187(): Adjusted OFDM Tx power level %d for we are in High Power state\n", ++ ofdm_power_level); ++ printk("SetTxPowerLevel8187(): Adjusted CCK Tx power level %d for we are in High Power state\n", ++ cck_power_level); ++ } ++ ++ ++ ++ /* CCK power setting */ ++ if(cck_power_level > max_cck_power_level) ++ cck_power_level = max_cck_power_level; ++ GainIdx=cck_power_level % 6; ++ GainSetting=cck_power_level / 6; ++ ++ if(ch == 14) ++ cck_power_table = rtl8225_tx_power_cck_ch14; ++ else ++ cck_power_table = rtl8225_tx_power_cck; ++ ++// if(priv->card_8185 == 1 && priv->card_8185_Bversion ){ ++ /*Ver B*/ ++// write_nic_byte(dev, TX_GAIN_CCK, rtl8225_tx_gain_cck_ofdm[GainSetting]); ++// }else{ ++ /*Ver C - D */ ++ write_nic_byte(dev, CCK_TXAGC, rtl8225_tx_gain_cck_ofdm[GainSetting]>>1); ++// } ++ ++ for(i=0;i<8;i++){ ++ ++ power = cck_power_table[GainIdx * 8 + i]; ++ write_phy_cck(dev, 0x44 + i, power); ++ } ++ ++ /* FIXME Is this delay really needeed ? */ ++ force_pci_posting(dev); ++ mdelay(1); ++ ++ /* OFDM power setting */ ++// Old: ++// if(ofdm_power_level > max_ofdm_power_level) ++// ofdm_power_level = 35; ++// ofdm_power_level += min_ofdm_power_level; ++// Latest: ++ if(ofdm_power_level > (max_ofdm_power_level - min_ofdm_power_level)) ++ ofdm_power_level = max_ofdm_power_level; ++ else ++ ofdm_power_level += min_ofdm_power_level; ++ if(ofdm_power_level > 35) ++ ofdm_power_level = 35; ++// ++ ++ GainIdx=ofdm_power_level % 6; ++ GainSetting=ofdm_power_level / 6; ++#if 1 ++// if(priv->card_type == USB){ ++ rtl8185_set_anaparam2(dev,RTL8225_ANAPARAM2_ON); ++ ++ write_phy_ofdm(dev,2,0x42); ++ write_phy_ofdm(dev,6,0); ++ write_phy_ofdm(dev,8,0); ++// } ++#endif ++// if(priv->card_8185 == 1 && priv->card_8185_Bversion){ ++// /*Ver B*/ ++// write_nic_byte(dev, TX_GAIN_OFDM, rtl8225_tx_gain_cck_ofdm[GainSetting]); ++// }else{ ++ /*Ver C - D */ ++ write_nic_byte(dev, OFDM_TXAGC, rtl8225_tx_gain_cck_ofdm[GainSetting]>>1); ++// } ++ ++ ++ power = rtl8225_tx_power_ofdm[GainIdx]; ++ ++ write_phy_ofdm(dev, 0x5, power); ++ write_phy_ofdm(dev, 0x7, power); ++ ++ force_pci_posting(dev); ++ mdelay(1); ++ //write_nic_byte(dev, TX_AGC_CONTROL,4); ++} ++ ++void rtl8225_rf_set_chan(struct net_device *dev, short ch) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ short gset = (priv->ieee80211->state == IEEE80211_LINKED && ++ ieee80211_is_54g(priv->ieee80211->current_network)) || ++ priv->ieee80211->iw_mode == IW_MODE_MONITOR; ++ int eifs_addr; ++ ++ if(NIC_8187 == priv->card_8187) { ++ eifs_addr = EIFS_8187; ++ } else { ++ eifs_addr = EIFS_8187B; ++ } ++ ++#ifdef ENABLE_DOT11D ++ if(!IsLegalChannel(priv->ieee80211, ch) ) ++ { ++ printk("channel(%d). is invalide\n", ch); ++ return; ++ } ++#endif ++ ++ rtl8225_SetTXPowerLevel(dev, ch); ++ ++ write_rtl8225(dev, 0x7, rtl8225_chan[ch]); ++ ++ force_pci_posting(dev); ++ mdelay(10); ++ ++ write_nic_byte(dev,SIFS,0x22);// SIFS: 0x22 ++ ++ if(gset) ++ write_nic_byte(dev,DIFS,20); //DIFS: 20 ++ else ++ write_nic_byte(dev,DIFS,0x24); //DIFS: 36 ++ ++ if(priv->ieee80211->state == IEEE80211_LINKED && ++ ieee80211_is_shortslot(priv->ieee80211->current_network)) ++ write_nic_byte(dev,SLOT,0x9); //SLOT: 9 ++ ++ else ++ write_nic_byte(dev,SLOT,0x14); //SLOT: 20 (0x14) ++ ++ ++ if(gset){ ++ write_nic_byte(dev,eifs_addr,91 - 20); // EIFS: 91 (0x5B) ++ write_nic_byte(dev,CW_VAL,0x73); //CW VALUE: 0x37 ++ //DMESG("using G net params"); ++ }else{ ++ write_nic_byte(dev,eifs_addr,91 - 0x24); // EIFS: 91 (0x5B) ++ write_nic_byte(dev,CW_VAL,0xa5); //CW VALUE: 0x37 ++ //DMESG("using B net params"); ++ } ++ ++ ++} ++ ++void rtl8225_host_pci_init(struct net_device *dev) ++{ ++ write_nic_word(dev, RFPinsOutput, 0x480); ++ ++ rtl8185_rf_pins_enable(dev); ++ ++ //if(priv->card_8185 == 2 && priv->enable_gpio0 ) /* version D */ ++ //write_nic_word(dev, RFPinsSelect, 0x88); ++ //else ++ write_nic_word(dev, RFPinsSelect, 0x88 | SW_CONTROL_GPIO); /* 0x488 | SW_CONTROL_GPIO */ ++ ++ write_nic_byte(dev, GP_ENABLE, 0); ++ ++ force_pci_posting(dev); ++ mdelay(200); ++ ++ write_nic_word(dev, GP_ENABLE, 0xff & (~(1<<6))); /* bit 6 is for RF on/off detection */ ++ ++ ++} ++ ++void rtl8225_host_usb_init(struct net_device *dev) ++{ ++ write_nic_byte(dev,RFPinsSelect+1,0); ++ ++ write_nic_byte(dev,GPIO,0); ++ ++ write_nic_byte_E(dev,0x53,read_nic_byte_E(dev,0x53) | (1<<7)); ++ ++ write_nic_byte(dev,RFPinsSelect+1,4); ++ ++ write_nic_byte(dev,GPIO,0x20); ++ ++ write_nic_byte(dev,GP_ENABLE,0); ++ ++ ++ /* Config BB & RF */ ++ write_nic_word(dev, RFPinsOutput, 0x80); ++ ++ write_nic_word(dev, RFPinsSelect, 0x80); ++ ++ write_nic_word(dev, RFPinsEnable, 0x80); ++ ++ ++ mdelay(100); ++ ++ mdelay(1000); ++ ++} ++ ++void rtl8225_rf_init(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int i; ++ short channel = 1; ++ u16 brsr; ++ int brsr_addr; ++ ++ if(NIC_8187 == priv->card_8187) { ++ brsr_addr = BRSR_8187; ++ } else { ++ brsr_addr = BRSR_8187B; ++ } ++ ++ ++ priv->chan = channel; ++ ++ rtl8180_set_anaparam(dev, RTL8225_ANAPARAM_ON); ++ ++ ++ if(priv->card_type == USB) ++ rtl8225_host_usb_init(dev); ++ else ++ rtl8225_host_pci_init(dev); ++ ++ write_nic_dword(dev, RF_TIMING, 0x000a8008); ++ ++ //brsr = read_nic_word(dev, BRSR); ++ brsr = read_nic_word(dev, brsr_addr); ++ ++ //write_nic_word(dev, BRSR, 0xffff); ++ write_nic_word(dev, brsr_addr, 0xffff); ++ ++ write_nic_dword(dev, RF_PARA, 0x100044); ++ ++ #if 1 //0->1 ++ rtl8180_set_mode(dev, EPROM_CMD_CONFIG); ++ write_nic_byte(dev, CONFIG3, 0x44); ++ rtl8180_set_mode(dev, EPROM_CMD_NORMAL); ++ #endif ++ ++ if(priv->card_type == USB){ ++ rtl8185_rf_pins_enable(dev); ++ ++ mdelay(1000); ++ } ++ ++ write_rtl8225(dev, 0x0, 0x67); mdelay(1); ++ ++ ++ write_rtl8225(dev, 0x1, 0xfe0); mdelay(1); ++ ++ write_rtl8225(dev, 0x2, 0x44d); mdelay(1); ++ ++ write_rtl8225(dev, 0x3, 0x441); mdelay(1); ++ ++ if(priv->card_type == USB) ++ write_rtl8225(dev, 0x4, 0x486); ++ else ++ write_rtl8225(dev, 0x4, 0x8be); ++ ++ mdelay(1); ++ ++ ++ /* version B & C */ ++ ++ if(priv->card_type == USB) ++ write_rtl8225(dev, 0x5, 0xbc0); ++ else if(priv->card_type == MINIPCI) ++ write_rtl8225(dev, 0x5, 0xbc0 + 3 +(6<<3)); ++ else ++ write_rtl8225(dev, 0x5, 0xbc0 + (6<<3)); ++ ++ mdelay(1); ++// } ++ ++ write_rtl8225(dev, 0x6, 0xae6); mdelay(1); ++ ++ write_rtl8225(dev, 0x7, ((priv->card_type == USB)? 0x82a : rtl8225_chan[channel])); mdelay(1); ++ ++ write_rtl8225(dev, 0x8, 0x1f); mdelay(1); ++ ++ write_rtl8225(dev, 0x9, 0x334); mdelay(1); ++ ++ write_rtl8225(dev, 0xa, 0xfd4); mdelay(1); ++ ++ write_rtl8225(dev, 0xb, 0x391); mdelay(1); ++ ++ write_rtl8225(dev, 0xc, 0x50); mdelay(1); ++ ++ ++ write_rtl8225(dev, 0xd, 0x6db); mdelay(1); ++ ++ write_rtl8225(dev, 0xe, 0x29); mdelay(1); ++ ++ write_rtl8225(dev, 0xf, 0x914); ++ ++ if(priv->card_type == USB){ ++ //force_pci_posting(dev); ++ mdelay(100); ++ } ++ ++ write_rtl8225(dev, 0x2, 0xc4d); ++ ++ if(priv->card_type == USB){ ++ // force_pci_posting(dev); ++ mdelay(200); ++ ++ write_rtl8225(dev, 0x2, 0x44d); ++ ++ // force_pci_posting(dev); ++ mdelay(100); ++ ++ }//End of if(priv->card_type == USB) ++ /* FIXME!! rtl8187 we have to check if calibrarion ++ * is successful and eventually cal. again (repeat ++ * the two write on reg 2) ++ */ ++ force_pci_posting(dev); ++ ++ mdelay(100); //200 for 8187 ++ ++ //if(priv->card_type != USB) /* maybe not needed even for 8185 */ ++// write_rtl8225(dev, 0x7, rtl8225_chan[channel]); ++ ++ write_rtl8225(dev, 0x0, 0x127); ++ ++ for(i=0;i<95;i++){ ++ write_rtl8225(dev, 0x1, (u8)(i+1)); ++ ++ /* version B & C & D*/ ++ ++ write_rtl8225(dev, 0x2, rtl8225bcd_rxgain[i]); ++ } ++ ++ write_rtl8225(dev, 0x0, 0x27); ++ ++ ++// //if(priv->card_type != USB){ ++// write_rtl8225(dev, 0x2, 0x44d); ++// write_rtl8225(dev, 0x7, rtl8225_chan[channel]); ++// write_rtl8225(dev, 0x2, 0x47d); ++// ++// force_pci_posting(dev); ++// mdelay(100); ++// ++// write_rtl8225(dev, 0x2, 0x44d); ++// //} ++ ++ write_rtl8225(dev, 0x0, 0x22f); ++ ++ if(priv->card_type != USB) ++ rtl8185_rf_pins_enable(dev); ++ ++ for(i=0;i<128;i++){ ++ write_phy_ofdm(dev, 0xb, rtl8225_agc[i]); ++ ++ mdelay(1); ++ write_phy_ofdm(dev, 0xa, (u8)i+ 0x80); ++ ++ mdelay(1); ++ } ++ ++ force_pci_posting(dev); ++ mdelay(1); ++ ++ write_phy_ofdm(dev, 0x0, 0x1); mdelay(1); ++ write_phy_ofdm(dev, 0x1, 0x2); mdelay(1); ++ write_phy_ofdm(dev, 0x2, ((priv->card_type == USB)? 0x42 : 0x62)); mdelay(1); ++ write_phy_ofdm(dev, 0x3, 0x0); mdelay(1); ++ write_phy_ofdm(dev, 0x4, 0x0); mdelay(1); ++ write_phy_ofdm(dev, 0x5, 0x0); mdelay(1); ++ write_phy_ofdm(dev, 0x6, 0x40); mdelay(1); ++ write_phy_ofdm(dev, 0x7, 0x0); mdelay(1); ++ write_phy_ofdm(dev, 0x8, 0x40); mdelay(1); ++ write_phy_ofdm(dev, 0x9, 0xfe); mdelay(1); ++ ++ /* ver C & D */ ++ write_phy_ofdm(dev, 0xa, 0x9); mdelay(1); ++ ++ //write_phy_ofdm(dev, 0x18, 0xef); ++ // } ++ //} ++ write_phy_ofdm(dev, 0xb, 0x80); mdelay(1); ++ ++ write_phy_ofdm(dev, 0xc, 0x1);mdelay(1); ++ ++ ++ //if(priv->card_type != USB) ++ //write_phy_ofdm(dev, 0xd, 0x33); // <> ++ ++ write_phy_ofdm(dev, 0xe, 0xd3);mdelay(1); ++ ++ write_phy_ofdm(dev, 0xf, 0x38);mdelay(1); ++/*ver D & 8187*/ ++// } ++ ++// if(priv->card_8185 == 1 && priv->card_8185_Bversion) ++// write_phy_ofdm(dev, 0x10, 0x04);/*ver B*/ ++// else ++ write_phy_ofdm(dev, 0x10, 0x84);mdelay(1); ++/*ver C & D & 8187*/ ++ ++ write_phy_ofdm(dev, 0x11, 0x06);mdelay(1); ++/*agc resp time 700*/ ++ ++ ++// if(priv->card_8185 == 2){ ++ /* Ver D & 8187*/ ++ write_phy_ofdm(dev, 0x12, 0x20);mdelay(1); ++ ++ write_phy_ofdm(dev, 0x13, 0x20);mdelay(1); ++ ++ write_phy_ofdm(dev, 0x14, 0x0); mdelay(1); ++ write_phy_ofdm(dev, 0x15, 0x40); mdelay(1); ++ write_phy_ofdm(dev, 0x16, 0x0); mdelay(1); ++ write_phy_ofdm(dev, 0x17, 0x40); mdelay(1); ++ ++// if (priv->card_type == USB) ++// write_phy_ofdm(dev, 0x18, 0xef); ++ ++ write_phy_ofdm(dev, 0x18, 0xef);mdelay(1); ++ ++ ++ write_phy_ofdm(dev, 0x19, 0x19); mdelay(1); ++ write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1); ++ ++// if (priv->card_type != USB){ ++// if(priv->card_8185 == 1 && priv->card_8185_Bversion) ++// write_phy_ofdm(dev, 0x1b, 0x66); /* Ver B */ ++// else ++ write_phy_ofdm(dev, 0x1b, 0x76);mdelay(1); ++ /* Ver C & D */ //FIXME:MAYBE not needed ++// } ++ ++ write_phy_ofdm(dev, 0x1c, 0x4);mdelay(1); ++ ++ /*ver D & 8187*/ ++ write_phy_ofdm(dev, 0x1e, 0x95);mdelay(1); ++ ++ write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1); ++ ++// } ++ ++ write_phy_ofdm(dev, 0x20, 0x1f);mdelay(1); ++ ++ write_phy_ofdm(dev, 0x21, 0x27);mdelay(1); ++ ++ write_phy_ofdm(dev, 0x22, 0x16);mdelay(1); ++ ++// if(priv->card_type != USB) ++ //write_phy_ofdm(dev, 0x23, 0x43); //FIXME maybe not needed // <> ++ ++ write_phy_ofdm(dev, 0x24, 0x46); mdelay(1); ++ write_phy_ofdm(dev, 0x25, 0x20); mdelay(1); ++ write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); ++ write_phy_ofdm(dev, 0x27, 0x88); mdelay(1); ++/* Ver C & D & 8187*/ ++ ++ // <> Set init. gain to m74dBm. ++ ++ rtl8225_set_gain(dev,4); ++ /*write_phy_ofdm(dev, 0x0d, 0x43); mdelay(1); ++ write_phy_ofdm(dev, 0x1b, 0x76); mdelay(1); ++ write_phy_ofdm(dev, 0x1d, 0xc5); mdelay(1); ++ write_phy_ofdm(dev, 0x23, 0x78); mdelay(1); ++*/ ++ //if(priv->card_type == USB); ++ // rtl8225_set_gain_usb(dev, 1); /* FIXME this '2' is random */ ++ ++ write_phy_cck(dev, 0x0, 0x98); mdelay(1); ++ write_phy_cck(dev, 0x3, 0x20); mdelay(1); ++ write_phy_cck(dev, 0x4, 0x7e); mdelay(1); ++ write_phy_cck(dev, 0x5, 0x12); mdelay(1); ++ write_phy_cck(dev, 0x6, 0xfc); mdelay(1); ++ write_phy_cck(dev, 0x7, 0x78);mdelay(1); ++ /* Ver C & D & 8187*/ ++ ++ write_phy_cck(dev, 0x8, 0x2e);mdelay(1); ++ ++ write_phy_cck(dev, 0x10, ((priv->card_type == USB) ? 0x9b: 0x93)); mdelay(1); ++ write_phy_cck(dev, 0x11, 0x88); mdelay(1); ++ write_phy_cck(dev, 0x12, 0x47); mdelay(1); ++ write_phy_cck(dev, 0x13, 0xd0); /* Ver C & D & 8187*/ ++ ++ write_phy_cck(dev, 0x19, 0x0); ++ write_phy_cck(dev, 0x1a, 0xa0); ++ write_phy_cck(dev, 0x1b, 0x8); ++ write_phy_cck(dev, 0x40, 0x86); /* CCK Carrier Sense Threshold */ ++ ++ write_phy_cck(dev, 0x41, 0x8d);mdelay(1); ++ ++ ++ write_phy_cck(dev, 0x42, 0x15); mdelay(1); ++ write_phy_cck(dev, 0x43, 0x18); mdelay(1); ++ write_phy_cck(dev, 0x44, 0x1f); mdelay(1); ++ write_phy_cck(dev, 0x45, 0x1e); mdelay(1); ++ write_phy_cck(dev, 0x46, 0x1a); mdelay(1); ++ write_phy_cck(dev, 0x47, 0x15); mdelay(1); ++ write_phy_cck(dev, 0x48, 0x10); mdelay(1); ++ write_phy_cck(dev, 0x49, 0xa); mdelay(1); ++ write_phy_cck(dev, 0x4a, 0x5); mdelay(1); ++ write_phy_cck(dev, 0x4b, 0x2); mdelay(1); ++ write_phy_cck(dev, 0x4c, 0x5);mdelay(1); ++ ++ ++ write_nic_byte(dev, 0x5b, 0x0d); mdelay(1); ++ ++ ++ ++// <> ++// // TESTR 0xb 8187 ++// write_phy_cck(dev, 0x10, 0x93);// & 0xfb); ++// ++// //if(priv->card_type != USB){ ++// write_phy_ofdm(dev, 0x2, 0x62); ++// write_phy_ofdm(dev, 0x6, 0x0); ++// write_phy_ofdm(dev, 0x8, 0x0); ++// //} ++ ++ rtl8225_SetTXPowerLevel(dev, channel); ++ ++ write_phy_cck(dev, 0x10, 0x9b); mdelay(1); /* Rx ant A, 0xdb for B */ ++ write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); /* Rx ant A, 0x10 for B */ ++ ++ rtl8185_tx_antenna(dev, 0x3); /* TX ant A, 0x0 for B */ ++ ++ /* switch to high-speed 3-wire ++ * last digit. 2 for both cck and ofdm ++ */ ++ if(priv->card_type == USB) ++ write_nic_dword(dev, 0x94, 0x3dc00002); ++ else{ ++ write_nic_dword(dev, 0x94, 0x15c00002); ++ rtl8185_rf_pins_enable(dev); ++ } ++ ++// if(priv->card_type != USB) ++// rtl8225_set_gain(dev, 4); /* FIXME this '1' is random */ // <> ++// rtl8225_set_mode(dev, 1); /* FIXME start in B mode */ // <> ++// ++// /* make sure is waken up! */ ++// write_rtl8225(dev,0x4, 0x9ff); ++// rtl8180_set_anaparam(dev, RTL8225_ANAPARAM_ON); ++// rtl8185_set_anaparam2(dev, RTL8225_ANAPARAM2_ON); ++ ++ rtl8225_rf_set_chan(dev, priv->chan); ++ ++ //write_nic_word(dev,BRSR,brsr); ++ ++} +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_rtl8225.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_rtl8225.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_rtl8225.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_rtl8225.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,77 @@ ++/* ++ This is part of the rtl8180-sa2400 driver ++ released under the GPL (See file COPYING for details). ++ Copyright (c) 2005 Andrea Merello ++ ++ This files contains programming code for the rtl8225 ++ radio frontend. ++ ++ *Many* thanks to Realtek Corp. for their great support! ++ ++*/ ++ ++#ifndef RTL8225H ++#define RTL8225H ++ ++#include "r8187.h" ++ ++#define RTL8225_ANAPARAM_ON 0xa0000a59 ++ ++// FIXME: OFF ANAPARAM MIGHT BE WRONG! ++#define RTL8225_ANAPARAM_OFF 0xa00beb59 ++#define RTL8225_ANAPARAM2_OFF 0x840dec11 ++ ++#define RTL8225_ANAPARAM2_ON 0x860c7312 ++ ++void rtl8225_rf_init(struct net_device *dev); ++void rtl8225z2_rf_init(struct net_device *dev); ++void rtl8225z2_rf_set_chan(struct net_device *dev, short ch); ++short rtl8225_is_V_z2(struct net_device *dev); ++void rtl8225_rf_set_chan(struct net_device *dev,short ch); ++void rtl8225_rf_close(struct net_device *dev); ++short rtl8225_rf_set_sens(struct net_device *dev, short sens); ++void rtl8225_host_pci_init(struct net_device *dev); ++void rtl8225_host_usb_init(struct net_device *dev); ++void write_rtl8225(struct net_device *dev, u8 adr, u16 data); ++void rtl8225z2_rf_set_mode(struct net_device *dev) ; ++void rtl8185_rf_pins_enable(struct net_device *dev); ++void rtl8180_set_mode(struct net_device *dev,int mode); ++void UpdateInitialGain(struct net_device *dev); ++void UpdateCCKThreshold(struct net_device *dev); ++void rtl8225_SetTXPowerLevel(struct net_device *dev, short ch); ++void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch); ++ ++#define RTL8225_RF_MAX_SENS 6 ++#define RTL8225_RF_DEF_SENS 4 ++ ++extern inline char GetTxOfdmHighPowerBias(struct net_device *dev) ++{ ++ // ++ // We should always adjust our Tx Power for 8187 and 8187B. ++ // It was ever recommended not to adjust Tx Power of 8187B with Atheros AP ++ // for throughput by David, but now we found it is not the issue to impact ++ // the Atheros's problem and also no adjustion for Tx Power will cause "low" ++ // throughput. By Bruce, 2007-07-03. ++ // ++ return 10; ++} ++ ++// ++// Description: ++// Return Tx power level to minus if we are in high power state. ++// ++// Note: ++// Adjust it according to RF if required. ++// ++extern inline char GetTxCckHighPowerBias(struct net_device *dev) ++{ ++ return 7; ++} ++ ++ ++ ++extern u8 rtl8225_agc[]; ++ ++extern u32 rtl8225_chan[]; ++ ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_rtl8225z2.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_rtl8225z2.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_rtl8225z2.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_rtl8225z2.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,2090 @@ ++/* ++ This is part of the rtl8180-sa2400 driver ++ released under the GPL (See file COPYING for details). ++ Copyright (c) 2005 Andrea Merello ++ ++ This files contains programming code for the rtl8225 ++ radio frontend. ++ ++ *Many* thanks to Realtek Corp. for their great support! ++ ++*/ ++ ++ ++ ++#include "r8180_hw.h" ++#include "r8180_rtl8225.h" ++#ifdef ENABLE_DOT11D ++#include "dot11d.h" ++#endif ++ ++//2005.11.16 ++u8 rtl8225z2_threshold[]={ ++ 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd, ++}; ++ ++// 0xd 0x19 0x1b 0x21 ++u8 rtl8225z2_gain_bg[]={ ++ 0x23, 0x15, 0xa5, // -82-1dbm ++ 0x23, 0x15, 0xb5, // -82-2dbm ++ 0x23, 0x15, 0xc5, // -82-3dbm ++ 0x33, 0x15, 0xc5, // -78dbm ++ 0x43, 0x15, 0xc5, // -74dbm ++ 0x53, 0x15, 0xc5, // -70dbm ++ 0x63, 0x15, 0xc5, // -66dbm ++}; ++ ++u8 rtl8225z2_gain_a[]={ ++ 0x13,0x27,0x5a,//,0x37,// -82dbm ++ 0x23,0x23,0x58,//,0x37,// -82dbm ++ 0x33,0x1f,0x56,//,0x37,// -82dbm ++ 0x43,0x1b,0x54,//,0x37,// -78dbm ++ 0x53,0x17,0x51,//,0x37,// -74dbm ++ 0x63,0x24,0x4f,//,0x37,// -70dbm ++ 0x73,0x0f,0x4c,//,0x37,// -66dbm ++}; ++static u32 MAC_REG_TABLE[][3]={ ++ {0xf0, 0x32, 0000}, {0xf1, 0x32, 0000}, {0xf2, 0x00, 0000}, {0xf3, 0x00, 0000}, ++ {0xf4, 0x32, 0000}, {0xf5, 0x43, 0000}, {0xf6, 0x00, 0000}, {0xf7, 0x00, 0000}, ++ {0xf8, 0x46, 0000}, {0xf9, 0xa4, 0000}, {0xfa, 0x00, 0000}, {0xfb, 0x00, 0000}, ++ {0xfc, 0x96, 0000}, {0xfd, 0xa4, 0000}, {0xfe, 0x00, 0000}, {0xff, 0x00, 0000}, ++ ++ {0x58, 0x4b, 0001}, {0x59, 0x00, 0001}, {0x5a, 0x4b, 0001}, {0x5b, 0x00, 0001}, ++ {0x60, 0x4b, 0001}, {0x61, 0x09, 0001}, {0x62, 0x4b, 0001}, {0x63, 0x09, 0001}, ++ {0xce, 0x0f, 0001}, {0xcf, 0x00, 0001}, {0xe0, 0xff, 0001}, {0xe1, 0x0f, 0001}, ++ {0xe2, 0x00, 0001}, {0xf0, 0x4e, 0001}, {0xf1, 0x01, 0001}, {0xf2, 0x02, 0001}, ++ {0xf3, 0x03, 0001}, {0xf4, 0x04, 0001}, {0xf5, 0x05, 0001}, {0xf6, 0x06, 0001}, ++ {0xf7, 0x07, 0001}, {0xf8, 0x08, 0001}, ++ ++ {0x4e, 0x00, 0002}, {0x0c, 0x04, 0002}, {0x21, 0x61, 0002}, {0x22, 0x68, 0002}, ++ {0x23, 0x6f, 0002}, {0x24, 0x76, 0002}, {0x25, 0x7d, 0002}, {0x26, 0x84, 0002}, ++ {0x27, 0x8d, 0002}, {0x4d, 0x08, 0002}, {0x50, 0x05, 0002}, {0x51, 0xf5, 0002}, ++ {0x52, 0x04, 0002}, {0x53, 0xa0, 0002}, {0x54, 0x1f, 0002}, {0x55, 0x23, 0002}, ++ {0x56, 0x45, 0002}, {0x57, 0x67, 0002}, {0x58, 0x08, 0002}, {0x59, 0x08, 0002}, ++ {0x5a, 0x08, 0002}, {0x5b, 0x08, 0002}, {0x60, 0x08, 0002}, {0x61, 0x08, 0002}, ++ {0x62, 0x08, 0002}, {0x63, 0x08, 0002}, {0x64, 0xcf, 0002}, {0x72, 0x56, 0002}, ++ {0x73, 0x9a, 0002}, ++ ++ {0x34, 0xf0, 0000}, {0x35, 0x0f, 0000}, {0x5b, 0x40, 0000}, {0x84, 0x88, 0000}, ++ {0x85, 0x24, 0000}, {0x88, 0x54, 0000}, {0x8b, 0xb8, 0000}, {0x8c, 0x07, 0000}, ++ {0x8d, 0x00, 0000}, {0x94, 0x1b, 0000}, {0x95, 0x12, 0000}, {0x96, 0x00, 0000}, ++ {0x97, 0x06, 0000}, {0x9d, 0x1a, 0000}, {0x9f, 0x10, 0000}, {0xb4, 0x22, 0000}, ++ {0xbe, 0x80, 0000}, {0xdb, 0x00, 0000}, {0xee, 0x00, 0000}, {0x91, 0x01, 0000}, ++ //lzm mode 0x91 form 0x03->0x01 open GPIO BIT1, ++ //because Polling methord will rurn off Radio ++ //the first time when read GPI(0x92). ++ //because after 0x91:bit1 form 1->0, there will ++ //be time for 0x92:bit1 form 0->1 ++ ++ {0x4c, 0x00, 0002}, {0x9f, 0x00, 0003}, {0x8c, 0x01, 0000}, {0x8d, 0x10, 0000}, ++ {0x8e, 0x08, 0000}, {0x8f, 0x00, 0000} ++}; ++ ++static u8 ZEBRA_AGC[]={ ++ 0, ++ 0x5e,0x5e,0x5e,0x5e,0x5d,0x5b,0x59,0x57,0x55,0x53,0x51,0x4f,0x4d,0x4b,0x49,0x47, ++ 0x45,0x43,0x41,0x3f,0x3d,0x3b,0x39,0x37,0x35,0x33,0x31,0x2f,0x2d,0x2b,0x29,0x27, ++ 0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x11,0x0f,0x0d,0x0b,0x09,0x07, ++ 0x05,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, ++ 0x19,0x19,0x19,0x019,0x19,0x19,0x19,0x19,0x19,0x20,0x21,0x22,0x23,0x24,0x25,0x26, ++ 0x26,0x27,0x27,0x28,0x28,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,0x2c,0x2c,0x2c,0x2d, ++ 0x2d,0x2d,0x2d,0x2e,0x2e,0x2e,0x2e,0x2f,0x2f,0x2f,0x30,0x30,0x31,0x31,0x31,0x31, ++ 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31 ++}; ++ ++static u32 ZEBRA_RF_RX_GAIN_TABLE[]={ ++ 0, ++ 0x0400,0x0401,0x0402,0x0403,0x0404,0x0405,0x0408,0x0409, ++ 0x040a,0x040b,0x0502,0x0503,0x0504,0x0505,0x0540,0x0541, ++ 0x0542,0x0543,0x0544,0x0545,0x0580,0x0581,0x0582,0x0583, ++ 0x0584,0x0585,0x0588,0x0589,0x058a,0x058b,0x0643,0x0644, ++ 0x0645,0x0680,0x0681,0x0682,0x0683,0x0684,0x0685,0x0688, ++ 0x0689,0x068a,0x068b,0x068c,0x0742,0x0743,0x0744,0x0745, ++ 0x0780,0x0781,0x0782,0x0783,0x0784,0x0785,0x0788,0x0789, ++ 0x078a,0x078b,0x078c,0x078d,0x0790,0x0791,0x0792,0x0793, ++ 0x0794,0x0795,0x0798,0x0799,0x079a,0x079b,0x079c,0x079d, ++ 0x07a0,0x07a1,0x07a2,0x07a3,0x07a4,0x07a5,0x07a8,0x07a9, ++ 0x03aa,0x03ab,0x03ac,0x03ad,0x03b0,0x03b1,0x03b2,0x03b3, ++ 0x03b4,0x03b5,0x03b8,0x03b9,0x03ba,0x03bb,0x03bb ++}; ++ ++// Use the new SD3 given param, by shien chang, 2006.07.14 ++ ++static u8 OFDM_CONFIG[]={ ++ // 0x00 ++ 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60, ++ 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, ++ ++ // 0x10 ++ 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26, ++ 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3, ++ ++ // 0x20 ++ 0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f, ++ 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00, ++ ++ // 0x30 ++ 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e, ++ 0x6d, 0x3c, 0xfb, 0x07//0xc7 ++ }; ++ ++//2005.11.16, ++u8 ZEBRA2_CCK_OFDM_GAIN_SETTING[]={ ++ 0x00,0x01,0x02,0x03,0x04,0x05, ++ 0x06,0x07,0x08,0x09,0x0a,0x0b, ++ 0x0c,0x0d,0x0e,0x0f,0x10,0x11, ++ 0x12,0x13,0x14,0x15,0x16,0x17, ++ 0x18,0x19,0x1a,0x1b,0x1c,0x1d, ++ 0x1e,0x1f,0x20,0x21,0x22,0x23, ++}; ++//- ++u16 rtl8225z2_rxgain[]={ ++ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, ++ 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, ++ 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, ++ 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, ++ 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, ++ 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, ++ 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, ++ 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, ++ 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, ++ 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, ++ 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, ++ 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb ++ ++}; ++ ++ ++/* ++ from 0 to 0x23 ++u8 rtl8225_tx_gain_cck_ofdm[]={ ++ 0x02,0x06,0x0e,0x1e,0x3e,0x7e ++}; ++*/ ++ ++//- ++u8 rtl8225z2_tx_power_ofdm[]={ ++ 0x42,0x00,0x40,0x00,0x40 ++}; ++ ++ ++//- ++u8 rtl8225z2_tx_power_cck_ch14[]={ ++ 0x36,0x35,0x2e,0x1b,0x00,0x00,0x00,0x00, ++ 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, ++ 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, ++ 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, ++}; ++ ++ ++//- ++u8 rtl8225z2_tx_power_cck[]={ ++ 0x36,0x35,0x2e,0x25,0x1c,0x12,0x09,0x04, ++ 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03, ++ 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03, ++ 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 ++}; ++ ++#ifdef ENABLE_DOT11D ++// ++// Description: ++// Map dBm into Tx power index according to ++// current HW model, for example, RF and PA, and ++// current wireless mode. ++// ++s8 ++rtl8187B_DbmToTxPwrIdx( ++ struct r8180_priv *priv, ++ WIRELESS_MODE WirelessMode, ++ s32 PowerInDbm ++ ) ++{ ++ bool bUseDefault = true; ++ s8 TxPwrIdx = 0; ++ ++#ifdef CONFIG_RTL818X_S ++ // ++ // 071011, SD3 SY: ++ // OFDM Power in dBm = Index * 0.5 + 0 ++ // CCK Power in dBm = Index * 0.25 + 13 ++ // ++ if(priv->card_8185 >= VERSION_8187S_B) ++ { ++ s32 tmp = 0; ++ ++ if(WirelessMode == WIRELESS_MODE_G) ++ { ++ bUseDefault = false; ++ tmp = (2 * PowerInDbm); ++ ++ if(tmp < 0) ++ TxPwrIdx = 0; ++ else if(tmp > 40) // 40 means 20 dBm. ++ TxPwrIdx = 40; ++ else ++ TxPwrIdx = (s8)tmp; ++ } ++ else if(WirelessMode == WIRELESS_MODE_B) ++ { ++ bUseDefault = false; ++ tmp = (4 * PowerInDbm) - 52; ++ ++ if(tmp < 0) ++ TxPwrIdx = 0; ++ else if(tmp > 28) // 28 means 20 dBm. ++ TxPwrIdx = 28; ++ else ++ TxPwrIdx = (s8)tmp; ++ } ++ } ++#endif ++ ++ // ++ // TRUE if we want to use a default implementation. ++ // We shall set it to FALSE when we have exact translation formular ++ // for target IC. 070622, by rcnjko. ++ // ++ if(bUseDefault) ++ { ++ if(PowerInDbm < 0) ++ TxPwrIdx = 0; ++ else if(PowerInDbm > 35) ++ TxPwrIdx = 35; ++ else ++ TxPwrIdx = (u8)PowerInDbm; ++ } ++ ++ return TxPwrIdx; ++} ++#endif ++ ++ ++void rtl8225z2_set_gain(struct net_device *dev, short gain) ++{ ++ u8* rtl8225_gain; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ u8 mode = priv->ieee80211->mode; ++ ++ if(mode == IEEE_B || mode == IEEE_G) ++ rtl8225_gain = rtl8225z2_gain_bg; ++ else ++ rtl8225_gain = rtl8225z2_gain_a; ++ ++ //write_phy_ofdm(dev, 0x0d, rtl8225_gain[gain * 3]); ++ //write_phy_ofdm(dev, 0x19, rtl8225_gain[gain * 3 + 1]); ++ //write_phy_ofdm(dev, 0x1b, rtl8225_gain[gain * 3 + 2]); ++ //2005.11.17, by ch-hsu ++ write_phy_ofdm(dev, 0x0b, rtl8225_gain[gain * 3]); ++ write_phy_ofdm(dev, 0x1b, rtl8225_gain[gain * 3 + 1]); ++ write_phy_ofdm(dev, 0x1d, rtl8225_gain[gain * 3 + 2]); ++ write_phy_ofdm(dev, 0x21, 0x37); ++ ++} ++ ++u32 read_rtl8225(struct net_device *dev, u8 adr) ++{ ++ u32 data2Write = ((u32)(adr & 0x1f)) << 27; ++ u32 dataRead; ++ u32 mask; ++ u16 oval,oval2,oval3,tmp; ++// ThreeWireReg twreg; ++// ThreeWireReg tdata; ++ int i; ++ short bit, rw; ++ ++ u8 wLength = 6; ++ u8 rLength = 12; ++ u8 low2high = 0; ++ ++ oval = read_nic_word(dev, RFPinsOutput); ++ oval2 = read_nic_word(dev, RFPinsEnable); ++ oval3 = read_nic_word(dev, RFPinsSelect); ++ write_nic_word(dev, RFPinsEnable, (oval2|0xf)); ++ write_nic_word(dev, RFPinsSelect, (oval3|0xf)); ++ ++ dataRead = 0; ++ ++ oval &= ~0xf; ++ ++ write_nic_word(dev, RFPinsOutput, oval | BB_HOST_BANG_EN ); udelay(4); ++ ++ write_nic_word(dev, RFPinsOutput, oval ); udelay(5); ++ ++ rw = 0; ++ ++ mask = (low2high) ? 0x01 : (((u32)0x01)<<(32-1)); ++ for(i = 0; i < wLength/2; i++) ++ { ++ bit = ((data2Write&mask) != 0) ? 1 : 0; ++ write_nic_word(dev, RFPinsOutput, bit|oval | rw); udelay(1); ++ ++ write_nic_word(dev, RFPinsOutput, bit|oval | BB_HOST_BANG_CLK | rw); udelay(2); ++ write_nic_word(dev, RFPinsOutput, bit|oval | BB_HOST_BANG_CLK | rw); udelay(2); ++ ++ mask = (low2high) ? (mask<<1): (mask>>1); ++ ++ if(i == 2) ++ { ++ rw = BB_HOST_BANG_RW; ++ write_nic_word(dev, RFPinsOutput, bit|oval | BB_HOST_BANG_CLK | rw); udelay(2); ++ write_nic_word(dev, RFPinsOutput, bit|oval | rw); udelay(2); ++ break; ++ } ++ ++ bit = ((data2Write&mask) != 0) ? 1: 0; ++ ++ write_nic_word(dev, RFPinsOutput, oval|bit|rw| BB_HOST_BANG_CLK); udelay(2); ++ write_nic_word(dev, RFPinsOutput, oval|bit|rw| BB_HOST_BANG_CLK); udelay(2); ++ ++ write_nic_word(dev, RFPinsOutput, oval| bit |rw); udelay(1); ++ ++ mask = (low2high) ? (mask<<1) : (mask>>1); ++ } ++ ++ //twreg.struc.clk = 0; ++ //twreg.struc.data = 0; ++ write_nic_word(dev, RFPinsOutput, rw|oval); udelay(2); ++ mask = (low2high) ? 0x01 : (((u32)0x01) << (12-1)); ++ ++ // We must set data pin to HW controled, otherwise RF can't driver it and ++ // value RF register won't be able to read back properly. 2006.06.13, by rcnjko. ++ write_nic_word(dev, RFPinsEnable,((oval2|0xe) & (~0x01))); ++ ++ for(i = 0; i < rLength; i++) ++ { ++ write_nic_word(dev, RFPinsOutput, rw|oval); udelay(1); ++ ++ write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK); udelay(2); ++ write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK); udelay(2); ++ write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK); udelay(2); ++ tmp = read_nic_word(dev, RFPinsInput); ++ ++ dataRead |= (tmp & BB_HOST_BANG_CLK ? mask : 0); ++ ++ write_nic_word(dev, RFPinsOutput, (rw|oval)); udelay(2); ++ ++ mask = (low2high) ? (mask<<1) : (mask>>1); ++ } ++ ++ write_nic_word(dev, RFPinsOutput, BB_HOST_BANG_EN|BB_HOST_BANG_RW|oval); udelay(2); ++ ++ write_nic_word(dev, RFPinsEnable, oval2); ++ write_nic_word(dev, RFPinsSelect, oval3); // Set To SW Switch ++ write_nic_word(dev, RFPinsOutput, 0x3a0); ++ ++ return dataRead; ++ ++} ++short rtl8225_is_V_z2(struct net_device *dev) ++{ ++ short vz2 = 1; ++ //set VCO-PDN pin ++// printk("%s()\n", __FUNCTION__); ++ write_nic_word(dev, RFPinsOutput, 0x0080); ++ write_nic_word(dev, RFPinsSelect, 0x0080); ++ write_nic_word(dev, RFPinsEnable, 0x0080); ++ ++ //lzm mod for up take too long time 20081201 ++ //mdelay(100); ++ //mdelay(1000); ++ ++ /* sw to reg pg 1 */ ++ write_rtl8225(dev, 0, 0x1b7); ++ /* reg 8 pg 1 = 23*/ ++ if( read_rtl8225(dev, 8) != 0x588) ++ vz2 = 0; ++ ++ else /* reg 9 pg 1 = 24 */ ++ if( read_rtl8225(dev, 9) != 0x700) ++ vz2 = 0; ++ ++ /* sw back to pg 0 */ ++ write_rtl8225(dev, 0, 0xb7); ++ ++ return vz2; ++ ++} ++ ++void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++// int GainIdx; ++// int GainSetting; ++ int i; ++ u8 power; ++ u8 *cck_power_table; ++ u8 max_cck_power_level; ++ u8 min_cck_power_level; ++ u8 max_ofdm_power_level; ++ u8 min_ofdm_power_level; ++ s8 cck_power_level = 0xff & priv->chtxpwr[ch]; ++ s8 ofdm_power_level = 0xff & priv->chtxpwr_ofdm[ch]; ++ u8 hw_version = priv->card_8187_Bversion; ++ ++#ifdef ENABLE_DOT11D ++ if(IS_DOT11D_ENABLE(priv->ieee80211) && ++ IS_DOT11D_STATE_DONE(priv->ieee80211) ) ++ { ++ //PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(priv->ieee80211); ++ u8 MaxTxPwrInDbm = DOT11D_GetMaxTxPwrInDbm(priv->ieee80211, ch); ++ u8 CckMaxPwrIdx = rtl8187B_DbmToTxPwrIdx(priv, WIRELESS_MODE_B, MaxTxPwrInDbm); ++ u8 OfdmMaxPwrIdx = rtl8187B_DbmToTxPwrIdx(priv, WIRELESS_MODE_G, MaxTxPwrInDbm); ++ ++ //printk("Max Tx Power dBm (%d) => CCK Tx power index : %d, OFDM Tx power index: %d\n", MaxTxPwrInDbm, CckMaxPwrIdx, OfdmMaxPwrIdx); ++ ++ //printk("EEPROM channel(%d) => CCK Tx power index: %d, OFDM Tx power index: %d\n", ++ // ch, cck_power_level, ofdm_power_level); ++ ++ if(cck_power_level > CckMaxPwrIdx) ++ cck_power_level = CckMaxPwrIdx; ++ if(ofdm_power_level > OfdmMaxPwrIdx) ++ ofdm_power_level = OfdmMaxPwrIdx; ++ } ++ ++ //priv->CurrentCckTxPwrIdx = cck_power_level; ++ //priv->CurrentOfdmTxPwrIdx = ofdm_power_level; ++#endif ++ ++ if (NIC_8187B == priv->card_8187) ++ { ++ if (hw_version == VERSION_8187B_B) ++ { ++ min_cck_power_level = 0; ++ max_cck_power_level = 15; ++ min_ofdm_power_level = 2; ++ max_ofdm_power_level = 17; ++ }else ++ { ++ min_cck_power_level = 7; ++ max_cck_power_level = 22; ++ min_ofdm_power_level = 10; ++ max_ofdm_power_level = 25; ++ } ++ ++ if( priv->TrSwitchState == TR_SW_TX ) ++ { ++ //printk("SetTxPowerLevel8187(): Origianl OFDM Tx power level %d, adjust value = %d\n", ofdm_power_level,GetTxOfdmHighPowerBias(dev)); ++ ofdm_power_level -= GetTxOfdmHighPowerBias(dev); ++ cck_power_level -= GetTxCckHighPowerBias(dev); ++ //printk("SetTxPowerLevel8187(): Adjusted OFDM Tx power level %d for we are in High Power state\n", ++ // ofdm_power_level); ++ //printk("SetTxPowerLevel8187(): Adjusted CCK Tx power level %d for we are in High Power state\n", ++ // cck_power_level); ++ } ++ /* CCK power setting */ ++ if(cck_power_level > (max_cck_power_level -min_cck_power_level)) ++ cck_power_level = max_cck_power_level; ++ else ++ cck_power_level += min_cck_power_level; ++ cck_power_level += priv->cck_txpwr_base; ++ ++ if(cck_power_level > 35) ++ cck_power_level = 35; ++ if(cck_power_level < 0) ++ cck_power_level = 0; ++ ++ if(ch == 14) ++ cck_power_table = rtl8225z2_tx_power_cck_ch14; ++ else ++ cck_power_table = rtl8225z2_tx_power_cck; ++ if (hw_version == VERSION_8187B_B) ++ { ++ if (cck_power_level <= 6){ ++ } ++ else if (cck_power_level <=11){ ++ cck_power_table += 8; ++ } ++ else{ ++ cck_power_table += (8*2); ++ } ++ }else{ ++ if (cck_power_level<=5){ ++ }else if(cck_power_level<=11){ ++ cck_power_table += 8; ++ }else if(cck_power_level <= 17){ ++ cck_power_table += 8*2; ++ }else{ ++ cck_power_table += 8*3; ++ } ++ } ++ ++ ++ ++ for(i=0;i<8;i++){ ++ ++ power = cck_power_table[i]; ++ write_phy_cck(dev, 0x44 + i, power); ++ } ++ ++ //write_nic_byte(dev, TX_GAIN_CCK, power); ++ //2005.11.17, ++ write_nic_byte(dev, CCK_TXAGC, (ZEBRA2_CCK_OFDM_GAIN_SETTING[cck_power_level]*2)); ++ ++// force_pci_posting(dev); ++// msleep(1); ++//in windows the delay was del from 85 to 87, ++//here we mod to sleep, or The CPU occupany is too hight. LZM 31/10/2008 ++ ++ /* OFDM power setting */ ++ // Old: ++ // if(ofdm_power_level > max_ofdm_power_level) ++ // ofdm_power_level = 35; ++ // ofdm_power_level += min_ofdm_power_level; ++ // Latest: ++ if(ofdm_power_level > (max_ofdm_power_level - min_ofdm_power_level)) ++ ofdm_power_level = max_ofdm_power_level; ++ else ++ ofdm_power_level += min_ofdm_power_level; ++ ++ ofdm_power_level += priv->ofdm_txpwr_base; ++ ++ if(ofdm_power_level > 35) ++ ofdm_power_level = 35; ++ ++ if(ofdm_power_level < 0) ++ ofdm_power_level = 0; ++ write_nic_byte(dev, OFDM_TXAGC, ZEBRA2_CCK_OFDM_GAIN_SETTING[ofdm_power_level]*2); ++ ++ if (hw_version == VERSION_8187B_B) ++ { ++ if(ofdm_power_level<=11){ ++ write_phy_ofdm(dev, 0x87, 0x60); ++ write_phy_ofdm(dev, 0x89, 0x60); ++ } ++ else{ ++ write_phy_ofdm(dev, 0x87, 0x5c); ++ write_phy_ofdm(dev, 0x89, 0x5c); ++ } ++ }else{ ++ if(ofdm_power_level<=11){ ++ write_phy_ofdm(dev, 0x87, 0x5c); ++ write_phy_ofdm(dev, 0x89, 0x5c); ++ } ++ if(ofdm_power_level<=17){ ++ write_phy_ofdm(dev, 0x87, 0x54); ++ write_phy_ofdm(dev, 0x89, 0x54); ++ } ++ else{ ++ write_phy_ofdm(dev, 0x87, 0x50); ++ write_phy_ofdm(dev, 0x89, 0x50); ++ } ++ } ++// force_pci_posting(dev); ++// msleep(1); ++//in windows the delay was del from 85 to 87, ++//and here we mod to sleep, or The CPU occupany is too hight. LZM 31/10/2008 ++ }else if(NIC_8187 == priv->card_8187) { ++ min_cck_power_level = 0; ++ max_cck_power_level = 15; ++ min_ofdm_power_level = 10; ++ max_ofdm_power_level = 25; ++ if(cck_power_level > (max_cck_power_level -min_cck_power_level)) ++ cck_power_level = max_cck_power_level; ++ else ++ cck_power_level += min_cck_power_level; ++ cck_power_level += priv->cck_txpwr_base; ++ ++ if(cck_power_level > 35) ++ cck_power_level = 35; ++ ++ if(ch == 14) ++ cck_power_table = rtl8225z2_tx_power_cck_ch14; ++ else ++ cck_power_table = rtl8225z2_tx_power_cck; ++ for(i=0;i<8;i++){ ++ power = cck_power_table[i]; ++ write_phy_cck(dev, 0x44 + i, power); ++ } ++ ++ //write_nic_byte(dev, TX_GAIN_CCK, power); ++ //2005.11.17, ++ write_nic_byte(dev, CCK_TXAGC, ZEBRA2_CCK_OFDM_GAIN_SETTING[cck_power_level]); ++ ++// force_pci_posting(dev); ++// msleep(1); ++//in windows the delay was del from 85 to 87, ++//and here we mod to sleep, or The CPU occupany is too hight. LZM 31/10/2008 ++ if(ofdm_power_level > (max_ofdm_power_level - min_ofdm_power_level)) ++ ofdm_power_level = max_ofdm_power_level; ++ else ++ ofdm_power_level += min_ofdm_power_level; ++ ++ ofdm_power_level += priv->ofdm_txpwr_base; ++ ++ if(ofdm_power_level > 35) ++ ofdm_power_level = 35; ++ write_nic_byte(dev, OFDM_TXAGC, ZEBRA2_CCK_OFDM_GAIN_SETTING[ofdm_power_level]); ++ ++ rtl8185_set_anaparam2(dev,RTL8225_ANAPARAM2_ON); ++ ++ write_phy_ofdm(dev,2,0x42); ++ write_phy_ofdm(dev,5,0); ++ write_phy_ofdm(dev,6,0x40); ++ write_phy_ofdm(dev,7,0); ++ write_phy_ofdm(dev,8,0x40); ++ } ++ ++} ++ ++void rtl8225z2_rf_set_chan(struct net_device *dev, short ch) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ short gset = (priv->ieee80211->state == IEEE80211_LINKED && ++ ieee80211_is_54g(priv->ieee80211->current_network)) || ++ priv->ieee80211->iw_mode == IW_MODE_MONITOR; ++ int eifs_addr; ++ ++ down(&priv->set_chan_sem); ++ ++ if(NIC_8187 == priv->card_8187) { ++ eifs_addr = EIFS_8187; ++ } else { ++ eifs_addr = EIFS_8187B; ++ } ++ ++#ifdef ENABLE_DOT11D ++ if(!IsLegalChannel(priv->ieee80211, ch) ) ++ { ++ printk("channel(%d). is invalide\n", ch); ++ up(&priv->set_chan_sem); ++ return; ++ } ++#endif ++ //87B not do it FIXME ++ rtl8225z2_SetTXPowerLevel(dev, ch); ++ ++ //write_nic_byte(dev,0x7,(u8)rtl8225_chan[ch]); ++ write_rtl8225(dev, 0x7, rtl8225_chan[ch]); ++ ++ force_pci_posting(dev); ++ //mdelay(10); ++//in windows the delay was del from 85 to 87, ++//and here we mod to sleep, or The CPU occupany is too hight. LZM 31/10/2008 ++ if(NIC_8187 == priv->card_8187){ ++ write_nic_byte(dev,SIFS,0x22);// SIFS: 0x22 ++ ++ if(gset) ++ write_nic_byte(dev,DIFS,20); //DIFS: 20 ++ else ++ write_nic_byte(dev,DIFS,0x24); //DIFS: 36 ++ ++ if(priv->ieee80211->state == IEEE80211_LINKED && ++ ieee80211_is_shortslot(priv->ieee80211->current_network)) ++ write_nic_byte(dev,SLOT,0x9); //SLOT: 9 ++ ++ else ++ write_nic_byte(dev,SLOT,0x14); //SLOT: 20 (0x14) ++ ++ ++ if(gset){ ++ write_nic_byte(dev,eifs_addr,91 - 20); // EIFS: 91 (0x5B) ++ write_nic_byte(dev,CW_VAL,0x73); //CW VALUE: 0x37 ++ //DMESG("using G net params"); ++ }else{ ++ write_nic_byte(dev,eifs_addr,91 - 0x24); // EIFS: 91 (0x5B) ++ write_nic_byte(dev,CW_VAL,0xa5); //CW VALUE: 0x37 ++ //DMESG("using B net params"); ++ } ++ } ++ ++ else { ++#ifdef THOMAS_TURBO ++ if(priv->ieee80211->current_network.Turbo_Enable && priv->ieee80211->iw_mode == IW_MODE_INFRA){ ++ write_nic_word(dev,AC_VO_PARAM,0x5114); ++ write_nic_word(dev,AC_VI_PARAM,0x5114); ++ write_nic_word(dev,AC_BE_PARAM,0x5114); ++ write_nic_word(dev,AC_BK_PARAM,0x5114); ++ } else { ++ write_nic_word(dev,AC_VO_PARAM,0x731c); ++ write_nic_word(dev,AC_VI_PARAM,0x731c); ++ write_nic_word(dev,AC_BE_PARAM,0x731c); ++ write_nic_word(dev,AC_BK_PARAM,0x731c); ++ } ++#endif ++ } ++ ++ up(&priv->set_chan_sem); ++} ++void ++MacConfig_87BASIC_HardCode(struct net_device *dev) ++{ ++ //============================================================================ ++ // MACREG.TXT ++ //============================================================================ ++ int nLinesRead = 0; ++ u32 u4bRegOffset, u4bRegValue, u4bPageIndex; ++ int i; ++ ++ nLinesRead=(sizeof(MAC_REG_TABLE)/3)/4; ++ ++ for(i = 0; i < nLinesRead; i++) ++ { ++ u4bRegOffset=MAC_REG_TABLE[i][0]; ++ u4bRegValue=MAC_REG_TABLE[i][1]; ++ u4bPageIndex=MAC_REG_TABLE[i][2]; ++ ++ u4bRegOffset|= (u4bPageIndex << 8); ++ ++ write_nic_byte(dev, u4bRegOffset, (u8)u4bRegValue); ++ } ++ //============================================================================ ++} ++ ++static void MacConfig_87BASIC(struct net_device *dev) ++{ ++ MacConfig_87BASIC_HardCode(dev); ++ ++ //============================================================================ ++ ++ // Follow TID_AC_MAP of WMac. ++ //PlatformEFIOWrite2Byte(dev, TID_AC_MAP, 0xfa50); ++ write_nic_word(dev, TID_AC_MAP, 0xfa50); ++ ++ // Interrupt Migration, Jong suggested we use set 0x0000 first, 2005.12.14, by rcnjko. ++ write_nic_word(dev, INT_MIG, 0x0000); ++ ++ // Prevent TPC to cause CRC error. Added by Annie, 2006-06-10. ++ write_nic_dword(dev, 0x1F0, 0x00000000); ++ write_nic_dword(dev, 0x1F4, 0x00000000); ++ write_nic_byte(dev, 0x1F8, 0x00); ++ ++ // For WiFi 5.2.2.5 Atheros AP performance. Added by Annie, 2006-06-12. ++ // PlatformIOWrite4Byte(dev, RFTiming, 0x0008e00f); ++ // Asked for by SD3 CM Lin, 2006.06.27, by rcnjko. ++ write_nic_dword(dev, RFTiming, 0x00004001); ++ ++#ifdef TODO ++ // Asked for by Victor, for 87B B-cut Rx FIFO overflow bug, 2006.06.27, by rcnjko. ++ if(dev->NdisUsbDev.CardInfo.USBIsHigh == FALSE) ++ { ++ PlatformEFIOWrite1Byte(dev, 0x24E, 0x01); ++ } ++#endif ++} ++ ++ ++// ++// Description: ++// Initialize RFE and read Zebra2 version code. ++// ++// 2005-08-01, by Annie. ++// ++void ++SetupRFEInitialTiming(struct net_device* dev) ++{ ++ //u32 data8, data9; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ // setup initial timing for RFE ++ // Set VCO-PDN pin. ++ write_nic_word(dev, RFPinsOutput, 0x0480); ++ write_nic_word(dev, RFPinsSelect, 0x2488); ++ write_nic_word(dev, RFPinsEnable, 0x1FFF); ++ ++ mdelay(100); ++ // Steven recommends: delay 1 sec for setting RF 1.8V. by Annie, 2005-04-28. ++ mdelay(1000); ++ ++ // ++ // TODO: Read Zebra version code if necessary. ++ // ++ priv->rf_chip = RF_ZEBRA2; ++} ++ ++ ++void ZEBRA_Config_87BASIC_HardCode(struct net_device* dev) ++{ ++ u32 i; ++ u32 addr,data; ++ u32 u4bRegOffset, u4bRegValue; ++ ++ ++ //============================================================================= ++ // RADIOCFG.TXT ++ //============================================================================= ++ write_rtl8225(dev, 0x00, 0x00b7); mdelay(1); ++ write_rtl8225(dev, 0x01, 0x0ee0); mdelay(1); ++ write_rtl8225(dev, 0x02, 0x044d); mdelay(1); ++ write_rtl8225(dev, 0x03, 0x0441); mdelay(1); ++ write_rtl8225(dev, 0x04, 0x08c3); mdelay(1); ++ write_rtl8225(dev, 0x05, 0x0c72); mdelay(1); ++ write_rtl8225(dev, 0x06, 0x00e6); mdelay(1); ++ write_rtl8225(dev, 0x07, 0x082a); mdelay(1); ++ write_rtl8225(dev, 0x08, 0x003f); mdelay(1); ++ write_rtl8225(dev, 0x09, 0x0335); mdelay(1); ++ write_rtl8225(dev, 0x0a, 0x09d4); mdelay(1); ++ write_rtl8225(dev, 0x0b, 0x07bb); mdelay(1); ++ write_rtl8225(dev, 0x0c, 0x0850); mdelay(1); ++ write_rtl8225(dev, 0x0d, 0x0cdf); mdelay(1); ++ write_rtl8225(dev, 0x0e, 0x002b); mdelay(1); ++ write_rtl8225(dev, 0x0f, 0x0114); mdelay(1); ++ ++ write_rtl8225(dev, 0x00, 0x01b7); mdelay(1); ++ ++ ++ for(i=1;i<=95;i++) ++ { ++ write_rtl8225(dev, 0x01, i);mdelay(1); ++ write_rtl8225(dev, 0x02, ZEBRA_RF_RX_GAIN_TABLE[i]); mdelay(1); ++ //DbgPrint("RF - 0x%x = 0x%x\n", i, ZEBRA_RF_RX_GAIN_TABLE[i]); ++ } ++ ++ write_rtl8225(dev, 0x03, 0x0080); mdelay(1); // write reg 18 ++ write_rtl8225(dev, 0x05, 0x0004); mdelay(1); // write reg 20 ++ write_rtl8225(dev, 0x00, 0x00b7); mdelay(1); // switch to reg0-reg15 ++ //lzm mod for up take too long time 20081201 ++#ifdef THOMAS_BEACON ++ msleep(1000);// Deay 1 sec. //0xfd ++ //msleep(1000);// Deay 1 sec. //0xfd ++ //msleep(1000);// Deay 1 sec. //0xfd ++ msleep(400);// Deay 1 sec. //0xfd ++#else ++ ++ mdelay(1000); ++ //mdelay(1000); ++ //mdelay(1000); ++ mdelay(400); ++#endif ++ write_rtl8225(dev, 0x02, 0x0c4d); mdelay(1); ++ //lzm mod for up take too long time 20081201 ++ //mdelay(1000); ++ //mdelay(1000); ++ msleep(100);// Deay 100 ms. //0xfe ++ msleep(100);// Deay 100 ms. //0xfe ++ write_rtl8225(dev, 0x02, 0x044d); mdelay(1); ++ write_rtl8225(dev, 0x00, 0x02bf); mdelay(1); //0x002f disable 6us corner change, 06f--> enable ++ ++ //============================================================================= ++ ++ //============================================================================= ++ // CCKCONF.TXT ++ //============================================================================= ++ /* ++ u4bRegOffset=0x41; ++ u4bRegValue=0xc8; ++ ++ //DbgPrint("\nCCK- 0x%x = 0x%x\n", u4bRegOffset, u4bRegValue); ++ WriteBB(dev, (0x01000080 | (u4bRegOffset & 0x7f) | ((u4bRegValue & 0xff) << 8))); ++ */ ++ ++ ++ //============================================================================= ++ ++ //============================================================================= ++ // Follow WMAC RTL8225_Config() ++ //============================================================================= ++// // ++// // enable EEM0 and EEM1 in 9346CR ++// PlatformEFIOWrite1Byte(dev, CR9346, PlatformEFIORead1Byte(dev, CR9346)|0xc0); ++// // enable PARM_En in Config3 ++// PlatformEFIOWrite1Byte(dev, CONFIG3, PlatformEFIORead1Byte(dev, CONFIG3)|0x40); ++// ++// PlatformEFIOWrite4Byte(dev, AnaParm2, ANAPARM2_ASIC_ON); //0x727f3f52 ++// PlatformEFIOWrite4Byte(dev, AnaParm, ANAPARM_ASIC_ON); //0x45090658 ++ ++ // power control ++ write_nic_byte(dev, CCK_TXAGC, 0x03); ++ write_nic_byte(dev, OFDM_TXAGC, 0x07); ++ write_nic_byte(dev, ANTSEL, 0x03); ++ ++// // disable PARM_En in Config3 ++// PlatformEFIOWrite1Byte(dev, CONFIG3, PlatformEFIORead1Byte(dev, CONFIG3)&0xbf); ++// // disable EEM0 and EEM1 in 9346CR ++// PlatformEFIOWrite1Byte(dev, CR9346, PlatformEFIORead1Byte(dev, CR9346)&0x3f); ++ //============================================================================= ++ ++ //============================================================================= ++ // AGC.txt ++ //============================================================================= ++ //write_nic_dword( dev, PhyAddr, 0x00001280); // Annie, 2006-05-05 ++ //write_phy_ofdm( dev, 0x00, 0x12); // David, 2006-08-01 ++ write_phy_ofdm( dev, 0x80, 0x12); // David, 2006-08-09 ++ ++ for (i=0; i<128; i++) ++ { ++ //DbgPrint("AGC - [%x+1] = 0x%x\n", i, ZEBRA_AGC[i+1]); ++ ++ data = ZEBRA_AGC[i+1]; ++ data = data << 8; ++ data = data | 0x0000008F; ++ ++ addr = i + 0x80; //enable writing AGC table ++ addr = addr << 8; ++ addr = addr | 0x0000008E; ++ ++ write_phy_ofdm(dev,data&0x7f,(data>>8)&0xff); ++ write_phy_ofdm(dev,addr&0x7f,(addr>>8)&0xff); ++ write_phy_ofdm(dev,0x0E,0x00); ++ } ++ ++ //write_nic_dword(dev, PhyAddr, 0x00001080); // Annie, 2006-05-05 ++ //write_phy_ofdm( dev, 0x00, 0x10); // David, 2006-08-01 ++ write_phy_ofdm( dev, 0x80, 0x10); // David, 2006-08-09 ++ ++ //============================================================================= ++ ++ //============================================================================= ++ // OFDMCONF.TXT ++ //============================================================================= ++ ++ for(i=0; i<60; i++) ++ { ++ u4bRegOffset=i; ++ u4bRegValue=OFDM_CONFIG[i]; ++ //u4bRegValue=OFDM_CONFIG3m82[i]; ++ ++ // write_nic_dword(dev,PhyAddr,(0x00000080 | (u4bRegOffset & 0x7f) | ((u4bRegValue & 0xff) << 8))); ++ write_phy_ofdm(dev,i,u4bRegValue); ++ } ++ ++ ++ //============================================================================= ++} ++ ++void ZEBRA_Config_87BASIC(struct net_device *dev) ++{ ++ ZEBRA_Config_87BASIC_HardCode(dev); ++} ++//by amy for DIG ++// ++// Description: ++// Update initial gain into PHY. ++// ++void ++UpdateCCKThreshold( ++ struct net_device *dev ++ ) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ // Update CCK Power Detection(0x41) value. ++ switch(priv->StageCCKTh) ++ { ++ case 0: ++// printk("Update CCK Stage 0: 88 \n"); ++ write_phy_cck(dev, 0xc1, 0x88);mdelay(1); ++ break; ++ ++ case 1: ++// printk("Update CCK Stage 1: 98 \n"); ++ write_phy_cck(dev, 0xc1, 0x98);mdelay(1); ++ break; ++ ++ case 2: ++// printk("Update CCK Stage 2: C8 \n"); ++ write_phy_cck(dev, 0xc1, 0xC8);mdelay(1); ++ break; ++ ++ case 3: ++// printk("Update CCK Stage 3: D8 \n"); ++ write_phy_cck(dev, 0xc1, 0xD8);mdelay(1); ++ break; ++ ++ default: ++// printk("Update CCK Stage %d ERROR!\n", pHalData->StageCCKTh); ++ break; ++ } ++} ++// ++// Description: ++// Update initial gain into PHY. ++// ++void ++UpdateInitialGain( ++ struct net_device *dev ++ ) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ //u8 u1Tmp=0; ++ ++ //printk("UpdateInitialGain(): InitialGain: %d RFChipID: %d\n", priv->InitialGain, priv->rf_chip); ++ ++ switch(priv->rf_chip) ++ { ++ case RF_ZEBRA: ++ case RF_ZEBRA2: ++ ++ // ++ // Note: ++ // Whenever we update this gain table, we should be careful about those who call it. ++ // Functions which call UpdateInitialGain as follows are important: ++ // (1)StaRateAdaptive87B ++ // (2)DIG_Zebra ++ // (3)ActSetWirelessMode8187 (when the wireless mode is "B" mode, we set the ++ // OFDM[0x17] = 0x26 to improve the Rx sensitivity). ++ // By Bruce, 2007-06-01. ++ // ++ ++ // ++ // SD3 C.M. Lin Initial Gain Table, by Bruce, 2007-06-01. ++ // ++ switch(priv->InitialGain) ++ { ++ case 1: //m861dBm ++ DMESG("RTL8187 + 8225 Initial Gain State 1: -82 dBm "); ++ write_phy_ofdm(dev, 0x97, 0x26); mdelay(1); ++ write_phy_ofdm(dev, 0xa4, 0x86); mdelay(1); ++ write_phy_ofdm(dev, 0x85, 0xfa); mdelay(1); ++ break; ++ ++ case 2: //m862dBm ++ DMESG("RTL8187 + 8225 Initial Gain State 2: -78 dBm "); ++ write_phy_ofdm(dev, 0x97, 0x36); mdelay(1);// Revise 0x26 to 0x36, by Roger, 2007.05.03. ++ write_phy_ofdm(dev, 0xa4, 0x86); mdelay(1); ++ write_phy_ofdm(dev, 0x85, 0xfa); mdelay(1); ++ break; ++ ++ case 3: //m863dBm ++ DMESG("RTL8187 + 8225 Initial Gain State 3: -78 dBm "); ++ write_phy_ofdm(dev, 0x97, 0x36); mdelay(1);// Revise 0x26 to 0x36, by Roger, 2007.05.03. ++ write_phy_ofdm(dev, 0xa4, 0x86); mdelay(1); ++ write_phy_ofdm(dev, 0x85, 0xfb); mdelay(1); ++ break; ++ ++ case 4: //m864dBm ++ DMESG("RTL8187 + 8225 Initial Gain State 4: -74 dBm "); ++ write_phy_ofdm(dev, 0x97, 0x46); mdelay(1);// Revise 0x26 to 0x36, by Roger, 2007.05.03. ++ write_phy_ofdm(dev, 0xa4, 0x86); mdelay(1); ++ write_phy_ofdm(dev, 0x85, 0xfb); mdelay(1); ++ break; ++ ++ case 5: //m82dBm ++ DMESG("RTL8187 + 8225 Initial Gain State 5: -74 dBm "); ++ write_phy_ofdm(dev, 0x97, 0x46); mdelay(1); ++ write_phy_ofdm(dev, 0xa4, 0x96); mdelay(1); ++ write_phy_ofdm(dev, 0x85, 0xfb); mdelay(1); ++ break; ++ ++ case 6: //m78dBm ++ DMESG("RTL8187 + 8225 Initial Gain State 6: -70 dBm "); ++ write_phy_ofdm(dev, 0x97, 0x56); mdelay(1); ++ write_phy_ofdm(dev, 0xa4, 0x96); mdelay(1); ++ write_phy_ofdm(dev, 0x85, 0xfc); mdelay(1); ++ break; ++ ++ case 7: //m74dBm ++ DMESG("RTL8187 + 8225 Initial Gain State 7: -70 dBm "); ++ write_phy_ofdm(dev, 0x97, 0x56); mdelay(1); ++ write_phy_ofdm(dev, 0xa4, 0xa6); mdelay(1); ++ write_phy_ofdm(dev, 0x85, 0xfc); mdelay(1); ++ break; ++ ++ // By Bruce, 2007-03-29. ++ case 8: ++ write_phy_ofdm(dev, 0x97, 0x66); mdelay(1); ++ write_phy_ofdm(dev, 0xa4, 0xb6); mdelay(1); ++ write_phy_ofdm(dev, 0x85, 0xfc); mdelay(1); ++ break; ++ ++ default: //MP ++ DMESG("RTL8187 + 8225 Initial Gain State: -82 dBm (default), InitialGain(%d)", priv->InitialGain); ++ write_phy_ofdm(dev, 0x97, 0x26); mdelay(1); ++ write_phy_ofdm(dev, 0xa4, 0x86); mdelay(1); ++ write_phy_ofdm(dev, 0x85, 0xfa); mdelay(1); ++ break; ++ } ++ break; ++ ++ default: ++ break; ++ } ++} ++//by amy for DIG ++void PhyConfig8187(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u8 btConfig4; ++ ++ btConfig4 = read_nic_byte(dev, CONFIG4); ++ priv->RFProgType = (btConfig4 & 0x03); ++ ++ ++ ++ switch(priv->rf_chip) ++ { ++ case RF_ZEBRA2: ++ ZEBRA_Config_87BASIC(dev); ++ break; ++ } ++ if(priv->bDigMechanism) ++ { ++ if(priv->InitialGain == 0) ++ priv->InitialGain = 4; ++ DMESG("DIG is enabled, set default initial gain index to %d", priv->InitialGain); ++ } ++ ++ // By Bruce, 2007-03-29. ++ UpdateCCKThreshold(dev); ++ // Update initial gain after PhyConfig comleted, asked for by SD3 CMLin. ++ UpdateInitialGain(dev); ++ return ; ++} ++ ++u8 GetSupportedWirelessMode8187(struct net_device* dev) ++{ ++ u8 btSupportedWirelessMode; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ btSupportedWirelessMode = 0; ++ ++ switch(priv->rf_chip) ++ { ++ case RF_ZEBRA: ++ case RF_ZEBRA2: ++ btSupportedWirelessMode = (WIRELESS_MODE_B | WIRELESS_MODE_G); ++ break; ++ default: ++ btSupportedWirelessMode = WIRELESS_MODE_B; ++ break; ++ } ++ return btSupportedWirelessMode; ++} ++ ++void ActUpdateChannelAccessSetting(struct net_device *dev, ++ int WirelessMode, ++ PCHANNEL_ACCESS_SETTING ChnlAccessSetting) ++{ ++ AC_CODING eACI; ++ AC_PARAM AcParam; ++#ifdef TODO ++ PSTA_QOS pStaQos = Adapter->MgntInfo.pStaQos; ++#endif ++ //bool bFollowLegacySetting = false; ++ ++ ++ switch( WirelessMode ) ++ { ++ case WIRELESS_MODE_A: ++ ChnlAccessSetting->SIFS_Timer = 0x22; ++ ChnlAccessSetting->DIFS_Timer = 34; // 34 = 16 + 2*9. 2006.06.07, by rcnjko. ++ ChnlAccessSetting->SlotTimeTimer = 9; ++ ChnlAccessSetting->EIFS_Timer = 23; ++ ChnlAccessSetting->CWminIndex = 4; ++ ChnlAccessSetting->CWmaxIndex = 10; ++ break; ++ ++ case WIRELESS_MODE_B: ++ ChnlAccessSetting->SIFS_Timer = 0x22; ++ ChnlAccessSetting->DIFS_Timer = 50; // 50 = 10 + 2*20. 2006.06.07, by rcnjko. ++ ChnlAccessSetting->SlotTimeTimer = 20; ++ ChnlAccessSetting->EIFS_Timer = 91; ++ ChnlAccessSetting->CWminIndex = 5; ++ ChnlAccessSetting->CWmaxIndex = 10; ++ break; ++ ++ case WIRELESS_MODE_G: ++ // ++ // ++ // TODO: We still don't know how to set up these registers, just follow WMAC to ++ // verify 8185B FPAG. ++ // ++ // ++ // Jong said CWmin/CWmax register are not functional in 8185B, ++ // so we shall fill channel access realted register into AC parameter registers, ++ // even in nQBss. ++ // ++ ChnlAccessSetting->SIFS_Timer = 0x22; // Suggested by Jong, 2005.12.08. ++ ChnlAccessSetting->SlotTimeTimer = 9; // 2006.06.07, by rcnjko. ++ ChnlAccessSetting->DIFS_Timer = 28; // 28 = 10 + 2*9. 2006.06.07, by rcnjko. ++ ChnlAccessSetting->EIFS_Timer = 0x5B; // Suggested by wcchu, it is the default value of EIFS register, 2005.12.08. ++#ifdef TODO ++ switch (Adapter->NdisUsbDev.CWinMaxMin) ++#else ++ switch (2) ++#endif ++ { ++ case 0:// 0: [max:7 min:1 ] ++ ChnlAccessSetting->CWminIndex = 1; ++ ChnlAccessSetting->CWmaxIndex = 7; ++ break; ++ case 1:// 1: [max:7 min:2 ] ++ ChnlAccessSetting->CWminIndex = 2; ++ ChnlAccessSetting->CWmaxIndex = 7; ++ break; ++ case 2:// 2: [max:7 min:3 ] ++ ChnlAccessSetting->CWminIndex = 3; ++ ChnlAccessSetting->CWmaxIndex = 7; ++ break; ++ case 3:// 3: [max:9 min:1 ] ++ ChnlAccessSetting->CWminIndex = 1; ++ ChnlAccessSetting->CWmaxIndex = 9; ++ break; ++ case 4:// 4: [max:9 min:2 ] ++ ChnlAccessSetting->CWminIndex = 2; ++ ChnlAccessSetting->CWmaxIndex = 9; ++ break; ++ case 5:// 5: [max:9 min:3 ] ++ ChnlAccessSetting->CWminIndex = 3; ++ ChnlAccessSetting->CWmaxIndex = 9; ++ break; ++ case 6:// 6: [max:A min:5 ] ++ ChnlAccessSetting->CWminIndex = 5; ++ ChnlAccessSetting->CWmaxIndex = 10; ++ break; ++ case 7:// 7: [max:A min:4 ] ++ ChnlAccessSetting->CWminIndex = 4; ++ ChnlAccessSetting->CWmaxIndex = 10; ++ break; ++ ++ default: ++ ChnlAccessSetting->CWminIndex = 1; ++ ChnlAccessSetting->CWmaxIndex = 7; ++ break; ++ } ++#ifdef TODO ++ if( Adapter->MgntInfo.OpMode == RT_OP_MODE_IBSS) ++ { ++ ChnlAccessSetting->CWminIndex= 4; ++ ChnlAccessSetting->CWmaxIndex= 10; ++ } ++#endif ++ break; ++ } ++ ++ ++ write_nic_byte(dev, SIFS, ChnlAccessSetting->SIFS_Timer); ++//{ update slot time related by david, 2006-7-21 ++ write_nic_byte(dev, SLOT, ChnlAccessSetting->SlotTimeTimer); // Rewrited from directly use PlatformEFIOWrite1Byte(), by Annie, 2006-03-29. ++#ifdef TODO ++ if(pStaQos->CurrentQosMode > QOS_DISABLE) ++ { ++ for(eACI = 0; eACI < AC_MAX; eACI++) ++ { ++ Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_AC_PARAM, \ ++ (pu1Byte)(&(pStaQos->WMMParamEle.AcParam[eACI])) ); ++ } ++ } ++ else ++#endif ++ { ++ u8 u1bAIFS = aSifsTime + (2 * ChnlAccessSetting->SlotTimeTimer ); ++ ++ write_nic_byte(dev, AC_VO_PARAM, u1bAIFS); ++ write_nic_byte(dev, AC_VI_PARAM, u1bAIFS); ++ write_nic_byte(dev, AC_BE_PARAM, u1bAIFS); ++ write_nic_byte(dev, AC_BK_PARAM, u1bAIFS); ++ } ++//} ++ ++ write_nic_byte(dev, EIFS_8187B, ChnlAccessSetting->EIFS_Timer); ++ write_nic_byte(dev, AckTimeOutReg, 0x5B); // Suggested by wcchu, it is the default value of EIFS register, 2005.12.08. ++#ifdef TODO ++ // Update ECWmin/ECWmax, AIFS, TXOP Limit of each AC to the value defined by SPEC. ++ if( pStaQos->CurrentQosMode > QOS_DISABLE ) ++ { // QoS mode. ++ if(pStaQos->QBssWirelessMode == WirelessMode) ++ { ++ // Follow AC Parameters of the QBSS. ++ for(eACI = 0; eACI < AC_MAX; eACI++) ++ { ++ Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_AC_PARAM, (pu1Byte)(&(pStaQos->WMMParamEle.AcParam[eACI])) ); ++ } ++ } ++ else ++ { ++ // Follow Default WMM AC Parameters. ++ bFollowLegacySetting = TRUE; ++ } ++ } ++ else ++ { // Legacy 802.11. ++ bFollowLegacySetting = TRUE; ++ } ++ ++ if(bFollowLegacySetting) ++#endif ++ if(true) ++ { ++ // ++ // Follow 802.11 seeting to AC parameter, all AC shall use the same parameter. ++ // 2005.12.01, by rcnjko. ++ // ++ AcParam.longData = 0; ++ AcParam.f.AciAifsn.f.AIFSN = 2; // Follow 802.11 DIFS. ++ AcParam.f.AciAifsn.f.ACM = 0; ++ AcParam.f.Ecw.f.ECWmin = ChnlAccessSetting->CWminIndex; // Follow 802.11 CWmin. ++ AcParam.f.Ecw.f.ECWmax = ChnlAccessSetting->CWmaxIndex; // Follow 802.11 CWmax. ++ AcParam.f.TXOPLimit = 0; ++ for(eACI = 0; eACI < AC_MAX; eACI++) ++ { ++ AcParam.f.AciAifsn.f.ACI = (u8)eACI; ++ { ++ PAC_PARAM pAcParam = (PAC_PARAM)(&AcParam); ++ AC_CODING eACI; ++ u8 u1bAIFS; ++ u32 u4bAcParam; ++ ++ // Retrive paramters to udpate. ++ eACI = pAcParam->f.AciAifsn.f.ACI; ++ u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * ChnlAccessSetting->SlotTimeTimer + aSifsTime; ++ u4bAcParam = ( (((u32)(pAcParam->f.TXOPLimit)) << AC_PARAM_TXOP_LIMIT_OFFSET) | ++ (((u32)(pAcParam->f.Ecw.f.ECWmax)) << AC_PARAM_ECW_MAX_OFFSET) | ++ (((u32)(pAcParam->f.Ecw.f.ECWmin)) << AC_PARAM_ECW_MIN_OFFSET) | ++ (((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET)); ++ ++ switch(eACI) ++ { ++ case AC1_BK: ++ write_nic_dword(dev, AC_BK_PARAM, u4bAcParam); ++ break; ++ ++ case AC0_BE: ++ write_nic_dword(dev, AC_BE_PARAM, u4bAcParam); ++ break; ++ ++ case AC2_VI: ++ write_nic_dword(dev, AC_VI_PARAM, u4bAcParam); ++ break; ++ ++ case AC3_VO: ++ write_nic_dword(dev, AC_VO_PARAM, u4bAcParam); ++ break; ++ ++ default: ++ printk(KERN_WARNING "SetHwReg8185(): invalid ACI: %d !\n", eACI); ++ break; ++ } ++ ++ // Cehck ACM bit. ++ // If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13. ++ //write_nic_byte(dev, ACM_CONTROL, pAcParam->f.AciAifsn); ++ { ++ PACI_AIFSN pAciAifsn = (PACI_AIFSN)(&pAcParam->f.AciAifsn); ++ AC_CODING eACI = pAciAifsn->f.ACI; ++ ++ //modified Joseph ++ //for 8187B AsynIORead issue ++#ifdef TODO ++ u8 AcmCtrl = pHalData->AcmControl; ++#else ++ u8 AcmCtrl = 0; ++#endif ++ if( pAciAifsn->f.ACM ) ++ { // ACM bit is 1. ++ switch(eACI) ++ { ++ case AC0_BE: ++ AcmCtrl |= (BEQ_ACM_EN|BEQ_ACM_CTL|ACM_HW_EN); // or 0x21 ++ break; ++ ++ case AC2_VI: ++ AcmCtrl |= (VIQ_ACM_EN|VIQ_ACM_CTL|ACM_HW_EN); // or 0x42 ++ break; ++ ++ case AC3_VO: ++ AcmCtrl |= (VOQ_ACM_EN|VOQ_ACM_CTL|ACM_HW_EN); // or 0x84 ++ break; ++ ++ default: ++ printk(KERN_WARNING "SetHwReg8185(): [HW_VAR_ACM_CTRL] ACM set\ ++ failed: eACI is %d\n", eACI ); ++ break; ++ } ++ } ++ else ++ { // ACM bit is 0. ++ switch(eACI) ++ { ++ case AC0_BE: ++ AcmCtrl &= ( (~BEQ_ACM_EN) & (~BEQ_ACM_CTL) & (~ACM_HW_EN) ); // and 0xDE ++ break; ++ ++ case AC2_VI: ++ AcmCtrl &= ( (~VIQ_ACM_EN) & (~VIQ_ACM_CTL) & (~ACM_HW_EN) ); // and 0xBD ++ break; ++ ++ case AC3_VO: ++ AcmCtrl &= ( (~VOQ_ACM_EN) & (~VOQ_ACM_CTL) & (~ACM_HW_EN) ); // and 0x7B ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ //printk(KERN_WARNING "SetHwReg8185(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl); ++ ++#ifdef TO_DO ++ pHalData->AcmControl = AcmCtrl; ++#endif ++ write_nic_byte(dev, ACM_CONTROL, AcmCtrl); ++ } ++ } ++ } ++ } ++} ++ ++void ActSetWirelessMode8187(struct net_device* dev, u8 btWirelessMode) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ struct ieee80211_device *ieee = priv->ieee80211; ++ //PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); ++ u8 btSupportedWirelessMode = GetSupportedWirelessMode8187(dev); ++ ++ if( (btWirelessMode & btSupportedWirelessMode) == 0 ) ++ { // Don't switch to unsupported wireless mode, 2006.02.15, by rcnjko. ++ printk(KERN_WARNING "ActSetWirelessMode8187(): WirelessMode(%d) is not supported (%d)!\n", ++ btWirelessMode, btSupportedWirelessMode); ++ return; ++ } ++ ++ // 1. Assign wireless mode to swtich if necessary. ++ if( (btWirelessMode == WIRELESS_MODE_AUTO) || ++ (btWirelessMode & btSupportedWirelessMode) == 0 ) ++ { ++ if((btSupportedWirelessMode & WIRELESS_MODE_A)) ++ { ++ btWirelessMode = WIRELESS_MODE_A; ++ } ++ else if((btSupportedWirelessMode & WIRELESS_MODE_G)) ++ { ++ btWirelessMode = WIRELESS_MODE_G; ++ } ++ else if((btSupportedWirelessMode & WIRELESS_MODE_B)) ++ { ++ btWirelessMode = WIRELESS_MODE_B; ++ } ++ else ++ { ++ printk(KERN_WARNING "MptActSetWirelessMode8187(): No valid wireless mode supported, \ ++ btSupportedWirelessMode(%x)!!!\n", btSupportedWirelessMode); ++ btWirelessMode = WIRELESS_MODE_B; ++ } ++ } ++ ++ // 2. Swtich band. ++ switch(priv->rf_chip) ++ { ++ case RF_ZEBRA: ++ case RF_ZEBRA2: ++ { ++ // Update current wireless mode if we swtich to specified band successfully. ++ ieee->mode = (WIRELESS_MODE)btWirelessMode; ++ } ++ break; ++ ++ default: ++ printk(KERN_WARNING "MptActSetWirelessMode8187(): unsupported RF: 0x%X !!!\n", priv->rf_chip); ++ break; ++ } ++ ++ // 4. Change related setting. ++ if( ieee->mode == WIRELESS_MODE_A ){ ++ DMESG("WIRELESS_MODE_A"); ++ } ++ else if(ieee->mode == WIRELESS_MODE_B ){ ++ DMESG("WIRELESS_MODE_B"); ++ } ++ else if( ieee->mode == WIRELESS_MODE_G ){ ++ DMESG("WIRELESS_MODE_G"); ++ } ++ ActUpdateChannelAccessSetting(dev, ieee->mode, &priv->ChannelAccessSetting ); ++//by amy 0305 ++#ifdef TODO ++ if(ieee->mode == WIRELESS_MODE_B && priv->InitialGain > pHalData->RegBModeGainStage) ++ { ++ pHalData->InitialGain = pHalData->RegBModeGainStage; // B mode, OFDM[0x17] = 26. ++ RT_TRACE(COMP_INIT | COMP_DIG, DBG_LOUD, ("ActSetWirelessMode8187(): update init_gain to index %d for B mode\n",pHalData->InitialGain)); ++ PlatformScheduleWorkItem( &(pHalData->UpdateDigWorkItem) ); ++ } ++// pAdapter->MgntInfo.dot11CurrentWirelessMode = pHalData->CurrentWirelessMode; ++// MgntSetRegdot11OperationalRateSet( pAdapter ); ++#endif ++//by amy 0305 ++} ++ ++ ++void ++InitializeExtraRegsOn8185(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ struct ieee80211_device *ieee = priv->ieee80211; ++ //RTL8185_TODO: Determine Retrylimit, TxAGC, AutoRateFallback control. ++ bool bUNIVERSAL_CONTROL_RL = false; // Enable per-packet tx retry, 2005.03.31, by rcnjko. ++ bool bUNIVERSAL_CONTROL_AGC = true;//false; ++ bool bUNIVERSAL_CONTROL_ANT = true;//false; ++ bool bAUTO_RATE_FALLBACK_CTL = true; ++ u8 val8; ++ ++ // Set up ACK rate. ++ // Suggested by wcchu, 2005.08.25, by rcnjko. ++ // 1. Initialize (MinRR, MaxRR) to (6,24) for A/G. ++ // 2. MUST Set RR before BRSR. ++ // 3. CCK must be basic rate. ++ if((ieee->mode == IEEE_G)||(ieee->mode == IEEE_A)) ++ { ++ write_nic_word(dev, BRSR_8187B, 0x0fff); ++ } ++ else ++ { ++ write_nic_word(dev, BRSR_8187B, 0x000f); ++ } ++ ++ ++ // Retry limit ++ val8 = read_nic_byte(dev, CW_CONF); ++ if(bUNIVERSAL_CONTROL_RL) ++ { ++ val8 &= (~CW_CONF_PERPACKET_RETRY_LIMIT); ++ } ++ else ++ { ++ val8 |= CW_CONF_PERPACKET_RETRY_LIMIT; ++ } ++ ++ write_nic_byte(dev, CW_CONF, val8); ++ ++ // Tx AGC ++ val8 = read_nic_byte(dev, TX_AGC_CTL); ++ if(bUNIVERSAL_CONTROL_AGC) ++ { ++ val8 &= (~TX_AGC_CTL_PER_PACKET_TXAGC); ++ write_nic_byte(dev, CCK_TXAGC, 128); ++ write_nic_byte(dev, OFDM_TXAGC, 128); ++ } ++ else ++ { ++ val8 |= TX_AGC_CTL_PER_PACKET_TXAGC; ++ } ++ write_nic_byte(dev, TX_AGC_CTL, val8); ++ ++ // Tx Antenna including Feedback control ++ val8 = read_nic_byte(dev, TX_AGC_CTL); ++ ++ if(bUNIVERSAL_CONTROL_ANT) ++ { ++ write_nic_byte(dev, ANTSEL, 0x00); ++ val8 &= (~TXAGC_CTL_PER_PACKET_ANT_SEL); ++ } ++ else ++ { ++ val8 |= TXAGC_CTL_PER_PACKET_ANT_SEL; ++ } ++ write_nic_byte(dev, TX_AGC_CTL, val8); ++ ++ // Auto Rate fallback control ++ val8 = read_nic_byte(dev, RATE_FALLBACK); ++ if( bAUTO_RATE_FALLBACK_CTL ) ++ { ++ val8 |= RATE_FALLBACK_CTL_ENABLE | RATE_FALLBACK_CTL_AUTO_STEP0; ++ ++ // We shall set up the ARFR according to user's setting. ++ write_nic_word(dev, ARFR, 0x0fff); // set 1M ~ 54M ++ } ++ else ++ { ++ val8 &= (~RATE_FALLBACK_CTL_ENABLE); ++ } ++ write_nic_byte(dev, RATE_FALLBACK, val8); ++ ++} ++/////////////////////////// ++void rtl8225z2_rf_init(struct net_device *dev) ++{ ++ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ if (NIC_8187B == priv->card_8187){ ++ struct ieee80211_device *ieee = priv->ieee80211; ++ u8 InitWirelessMode; ++ u8 SupportedWirelessMode; ++ bool bInvalidWirelessMode = false; ++ InitializeExtraRegsOn8185(dev); ++ ++ write_nic_byte(dev, MSR, read_nic_byte(dev,MSR) & 0xf3); // default network type to 'No Link' ++ //{to avoid tx stall ++ write_nic_byte(dev, MSR, read_nic_byte(dev, MSR)|MSR_LINK_ENEDCA);//should always set ENDCA bit ++ write_nic_byte(dev, ACM_CONTROL, priv->AcmControl); ++ ++ write_nic_word(dev, BcnIntv, 100); ++ write_nic_word(dev, AtimWnd, 2); ++ write_nic_word(dev, FEMR, 0xFFFF); ++ //LED TYPE ++ { ++ write_nic_byte(dev, CONFIG1,((read_nic_byte(dev, CONFIG1)&0x3f)|0x80)); //turn on bit 5:Clkrun_mode ++ } ++ write_nic_byte(dev, CR9346, 0x0); // disable config register write ++ ++ //{ add some info here ++ write_nic_dword(dev, MAC0, ((u32*)dev->dev_addr)[0]); ++ write_nic_word(dev, MAC4, ((u32*)dev->dev_addr)[1] & 0xffff ); ++ ++ write_nic_byte(dev, WPA_CONFIG, 0); ++ //} ++ ++ MacConfig_87BASIC(dev); ++ ++ // Override the RFSW_CTRL (MAC offset 0x272-0x273), 2006.06.07, by rcnjko. ++ write_nic_word(dev, RFSW_CTRL, 0x569a); ++#ifdef JOHN_TKIP ++ { ++ void CamResetAllEntry(struct net_device *dev); ++ void EnableHWSecurityConfig8187(struct net_device *dev); ++ CamResetAllEntry(dev); ++ EnableHWSecurityConfig8187(dev); ++ write_nic_word(dev, AESMSK_FC, AESMSK_FC_DEFAULT); mdelay(1); ++ write_nic_word(dev, AESMSK_SC, AESMSK_SC_DEFAULT); mdelay(1); ++ write_nic_word(dev, AESMSK_QC, AESMSK_QC_DEFAULT); mdelay(1); ++ } ++#endif ++ //----------------------------------------------------------------------------- ++ // Set up PHY related. ++ //----------------------------------------------------------------------------- ++ // Enable Config3.PARAM_En to revise AnaaParm. ++ write_nic_byte(dev, CR9346, 0xC0); ++ write_nic_byte(dev, CONFIG3, read_nic_byte(dev,CONFIG3)|CONFIG3_PARM_En); ++ write_nic_byte(dev, CR9346, 0x0); ++ ++ // Initialize RFE and read Zebra2 version code. Added by Annie, 2005-08-01. ++ SetupRFEInitialTiming(dev); ++ // PHY config. ++ PhyConfig8187(dev); ++ ++ // We assume RegWirelessMode has already been initialized before, ++ // however, we has to validate the wireless mode here and provide a reasonble ++ // initialized value if necessary. 2005.01.13, by rcnjko. ++ SupportedWirelessMode = GetSupportedWirelessMode8187(dev); ++ ++ if((ieee->mode != WIRELESS_MODE_B) && ++ (ieee->mode != WIRELESS_MODE_G) && ++ (ieee->mode != WIRELESS_MODE_A) && ++ (ieee->mode != WIRELESS_MODE_AUTO)) ++ { // It should be one of B, G, A, or AUTO. ++ bInvalidWirelessMode = true; ++ } ++ else ++ { // One of B, G, A, or AUTO. ++ // Check if the wireless mode is supported by RF. ++ if( (ieee->mode != WIRELESS_MODE_AUTO) && ++ (ieee->mode & SupportedWirelessMode) == 0 ) ++ { ++ bInvalidWirelessMode = true; ++ } ++ } ++ ++ if(bInvalidWirelessMode || ieee->mode==WIRELESS_MODE_AUTO) ++ { // Auto or other invalid value. ++ // Assigne a wireless mode to initialize. ++ if((SupportedWirelessMode & WIRELESS_MODE_A)) ++ { ++ InitWirelessMode = WIRELESS_MODE_A; ++ } ++ else if((SupportedWirelessMode & WIRELESS_MODE_G)) ++ { ++ ++ InitWirelessMode = WIRELESS_MODE_G; ++ } ++ else if((SupportedWirelessMode & WIRELESS_MODE_B)) ++ { ++ ++ InitWirelessMode = WIRELESS_MODE_B; ++ } ++ else ++ { ++ printk(KERN_WARNING ++ "InitializeAdapter8187(): No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", ++ SupportedWirelessMode); ++ InitWirelessMode = WIRELESS_MODE_B; ++ } ++ ++ // Initialize RegWirelessMode if it is not a valid one. ++ if(bInvalidWirelessMode) ++ { ++ ieee->mode = (WIRELESS_MODE)InitWirelessMode; ++ } ++ } ++ else ++ { // One of B, G, A. ++ InitWirelessMode = ieee->mode; ++ } ++ ActSetWirelessMode8187(dev, (u8)(InitWirelessMode)); ++ {//added for init gain ++ write_phy_ofdm(dev, 0x97, 0x46); mdelay(1); ++ write_phy_ofdm(dev, 0xa4, 0xb6); mdelay(1); ++ write_phy_ofdm(dev, 0x85, 0xfc); mdelay(1); ++ write_phy_cck(dev, 0xc1, 0x88); mdelay(1); ++ } ++ ++ } ++ else{ ++ int i; ++ short channel = 1; ++ u16 brsr; ++ u32 data,addr; ++ ++ priv->chan = channel; ++ ++ rtl8180_set_anaparam(dev, RTL8225_ANAPARAM_ON); ++ ++ if(priv->card_type == USB) ++ rtl8225_host_usb_init(dev); ++ else ++ rtl8225_host_pci_init(dev); ++ ++ write_nic_dword(dev, RF_TIMING, 0x000a8008); ++ ++ brsr = read_nic_word(dev, BRSR_8187); ++ ++ write_nic_word(dev, BRSR_8187, 0xffff); ++ ++ ++ write_nic_dword(dev, RF_PARA, 0x100044); ++ ++ #if 1 //0->1 ++ rtl8180_set_mode(dev, EPROM_CMD_CONFIG); ++ write_nic_byte(dev, CONFIG3, 0x44); ++ rtl8180_set_mode(dev, EPROM_CMD_NORMAL); ++ #endif ++ ++ ++ rtl8185_rf_pins_enable(dev); ++ ++ // mdelay(1000); ++ ++ write_rtl8225(dev, 0x0, 0x2bf); mdelay(1); ++ ++ ++ write_rtl8225(dev, 0x1, 0xee0); mdelay(1); ++ ++ write_rtl8225(dev, 0x2, 0x44d); mdelay(1); ++ ++ write_rtl8225(dev, 0x3, 0x441); mdelay(1); ++ ++ ++ write_rtl8225(dev, 0x4, 0x8c3);mdelay(1); ++ ++ ++ ++ write_rtl8225(dev, 0x5, 0xc72);mdelay(1); ++ // } ++ ++ write_rtl8225(dev, 0x6, 0xe6); mdelay(1); ++ ++ write_rtl8225(dev, 0x7, ((priv->card_type == USB)? 0x82a : rtl8225_chan[channel])); mdelay(1); ++ ++ write_rtl8225(dev, 0x8, 0x3f); mdelay(1); ++ ++ write_rtl8225(dev, 0x9, 0x335); mdelay(1); ++ ++ write_rtl8225(dev, 0xa, 0x9d4); mdelay(1); ++ ++ write_rtl8225(dev, 0xb, 0x7bb); mdelay(1); ++ ++ write_rtl8225(dev, 0xc, 0x850); mdelay(1); ++ ++ ++ write_rtl8225(dev, 0xd, 0xcdf); mdelay(1); ++ ++ write_rtl8225(dev, 0xe, 0x2b); mdelay(1); ++ ++ write_rtl8225(dev, 0xf, 0x114); ++ ++ ++ mdelay(100); ++ ++ ++ //if(priv->card_type != USB) /* maybe not needed even for 8185 */ ++ // write_rtl8225(dev, 0x7, rtl8225_chan[channel]); ++ ++ write_rtl8225(dev, 0x0, 0x1b7); ++ ++ for(i=0;i<95;i++){ ++ write_rtl8225(dev, 0x1, (u8)(i+1)); ++ /* version B & C & D*/ ++ write_rtl8225(dev, 0x2, rtl8225z2_rxgain[i]); ++ } ++ //write_rtl8225(dev, 0x3, 0x80); ++ write_rtl8225(dev, 0x3, 0x2); ++ write_rtl8225(dev, 0x5, 0x4); ++ ++ write_rtl8225(dev, 0x0, 0xb7); ++ ++ write_rtl8225(dev, 0x2, 0xc4d); ++ ++ if(priv->card_type == USB){ ++ // force_pci_posting(dev); ++ mdelay(200); ++ ++ write_rtl8225(dev, 0x2, 0x44d); ++ ++ // force_pci_posting(dev); ++ mdelay(200); ++ ++ }//End of if(priv->card_type == USB) ++ /* FIXME!! rtl8187 we have to check if calibrarion ++ * is successful and eventually cal. again (repeat ++ * the two write on reg 2) ++ */ ++ // Check for calibration status, 2005.11.17, ++ data = read_rtl8225(dev, 6); ++ if (!(data&0x00000080)) ++ { ++ write_rtl8225(dev, 0x02, 0x0c4d); ++ force_pci_posting(dev); mdelay(200); ++ write_rtl8225(dev, 0x02, 0x044d); ++ force_pci_posting(dev); mdelay(100); ++ data = read_rtl8225(dev, 6); ++ if (!(data&0x00000080)) ++ { ++ DMESGW("RF Calibration Failed!!!!\n"); ++ } ++ } ++ //force_pci_posting(dev); ++ ++ mdelay(200); //200 for 8187 ++ ++ ++ // //if(priv->card_type != USB){ ++ // write_rtl8225(dev, 0x2, 0x44d); ++ // write_rtl8225(dev, 0x7, rtl8225_chan[channel]); ++ // write_rtl8225(dev, 0x2, 0x47d); ++ // ++ // force_pci_posting(dev); ++ // mdelay(100); ++ // ++ // write_rtl8225(dev, 0x2, 0x44d); ++ // //} ++ ++ write_rtl8225(dev, 0x0, 0x2bf); ++ ++ if(priv->card_type != USB) ++ rtl8185_rf_pins_enable(dev); ++ //set up ZEBRA AGC table, 2005.11.17, ++ for(i=0;i<128;i++){ ++ data = rtl8225_agc[i]; ++ ++ addr = i + 0x80; //enable writing AGC table ++ write_phy_ofdm(dev, 0xb, data); ++ ++ mdelay(1); ++ write_phy_ofdm(dev, 0xa, addr); ++ ++ mdelay(1); ++ } ++ ++ force_pci_posting(dev); ++ mdelay(1); ++ ++ write_phy_ofdm(dev, 0x0, 0x1); mdelay(1); ++ write_phy_ofdm(dev, 0x1, 0x2); mdelay(1); ++ write_phy_ofdm(dev, 0x2, ((priv->card_type == USB)? 0x42 : 0x62)); mdelay(1); ++ write_phy_ofdm(dev, 0x3, 0x0); mdelay(1); ++ write_phy_ofdm(dev, 0x4, 0x0); mdelay(1); ++ write_phy_ofdm(dev, 0x5, 0x0); mdelay(1); ++ write_phy_ofdm(dev, 0x6, 0x40); mdelay(1); ++ write_phy_ofdm(dev, 0x7, 0x0); mdelay(1); ++ write_phy_ofdm(dev, 0x8, 0x40); mdelay(1); ++ write_phy_ofdm(dev, 0x9, 0xfe); mdelay(1); ++ ++ write_phy_ofdm(dev, 0xa, 0x8); mdelay(1); ++ ++ //write_phy_ofdm(dev, 0x18, 0xef); ++ // } ++ //} ++ write_phy_ofdm(dev, 0xb, 0x80); mdelay(1); ++ ++ write_phy_ofdm(dev, 0xc, 0x1);mdelay(1); ++ ++ ++ //if(priv->card_type != USB) ++ write_phy_ofdm(dev, 0xd, 0x43); ++ ++ write_phy_ofdm(dev, 0xe, 0xd3);mdelay(1); ++ ++ write_phy_ofdm(dev, 0xf, 0x38);mdelay(1); ++ /*ver D & 8187*/ ++ // } ++ ++ // if(priv->card_8185 == 1 && priv->card_8185_Bversion) ++ // write_phy_ofdm(dev, 0x10, 0x04);/*ver B*/ ++ // else ++ write_phy_ofdm(dev, 0x10, 0x84);mdelay(1); ++ /*ver C & D & 8187*/ ++ ++ write_phy_ofdm(dev, 0x11, 0x07);mdelay(1); ++ /*agc resp time 700*/ ++ ++ ++ // if(priv->card_8185 == 2){ ++ /* Ver D & 8187*/ ++ write_phy_ofdm(dev, 0x12, 0x20);mdelay(1); ++ ++ write_phy_ofdm(dev, 0x13, 0x20);mdelay(1); ++ ++ write_phy_ofdm(dev, 0x14, 0x0); mdelay(1); ++ write_phy_ofdm(dev, 0x15, 0x40); mdelay(1); ++ write_phy_ofdm(dev, 0x16, 0x0); mdelay(1); ++ write_phy_ofdm(dev, 0x17, 0x40); mdelay(1); ++ ++ // if (priv->card_type == USB) ++ // write_phy_ofdm(dev, 0x18, 0xef); ++ ++ write_phy_ofdm(dev, 0x18, 0xef);mdelay(1); ++ ++ ++ write_phy_ofdm(dev, 0x19, 0x19); mdelay(1); ++ write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1); ++ write_phy_ofdm(dev, 0x1b, 0x15);mdelay(1); ++ ++ write_phy_ofdm(dev, 0x1c, 0x4);mdelay(1); ++ ++ write_phy_ofdm(dev, 0x1d, 0xc5);mdelay(1); //2005.11.17, ++ ++ write_phy_ofdm(dev, 0x1e, 0x95);mdelay(1); ++ ++ write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1); ++ ++ // } ++ ++ write_phy_ofdm(dev, 0x20, 0x1f);mdelay(1); ++ ++ write_phy_ofdm(dev, 0x21, 0x17);mdelay(1); ++ ++ write_phy_ofdm(dev, 0x22, 0x16);mdelay(1); ++ ++ // if(priv->card_type != USB) ++ write_phy_ofdm(dev, 0x23, 0x80);mdelay(1); //FIXME maybe not needed // <> ++ ++ write_phy_ofdm(dev, 0x24, 0x46); mdelay(1); ++ write_phy_ofdm(dev, 0x25, 0x00); mdelay(1); ++ write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); ++ ++ write_phy_ofdm(dev, 0x27, 0x88); mdelay(1); ++ ++ ++ // <> Set init. gain to m74dBm. ++ ++ rtl8225z2_set_gain(dev,4); ++ //rtl8225z2_set_gain(dev,2); ++ ++ write_phy_cck(dev, 0x0, 0x98); mdelay(1); ++ write_phy_cck(dev, 0x3, 0x20); mdelay(1); ++ write_phy_cck(dev, 0x4, 0x7e); mdelay(1); ++ write_phy_cck(dev, 0x5, 0x12); mdelay(1); ++ write_phy_cck(dev, 0x6, 0xfc); mdelay(1); ++ write_phy_cck(dev, 0x7, 0x78);mdelay(1); ++ /* Ver C & D & 8187*/ ++ write_phy_cck(dev, 0x8, 0x2e);mdelay(1); ++ ++ write_phy_cck(dev, 0x9, 0x11);mdelay(1); ++ write_phy_cck(dev, 0xa, 0x17);mdelay(1); ++ write_phy_cck(dev, 0xb, 0x11);mdelay(1); ++ ++ write_phy_cck(dev, 0x10, ((priv->card_type == USB) ? 0x9b: 0x93)); mdelay(1); ++ write_phy_cck(dev, 0x11, 0x88); mdelay(1); ++ write_phy_cck(dev, 0x12, 0x47); mdelay(1); ++ write_phy_cck(dev, 0x13, 0xd0); /* Ver C & D & 8187*/ ++ ++ write_phy_cck(dev, 0x19, 0x0); mdelay(1); ++ write_phy_cck(dev, 0x1a, 0xa0); mdelay(1); ++ write_phy_cck(dev, 0x1b, 0x8); mdelay(1); ++ write_phy_cck(dev, 0x1d, 0x0); mdelay(1); ++ ++ write_phy_cck(dev, 0x40, 0x86); /* CCK Carrier Sense Threshold */ mdelay(1); ++ ++ write_phy_cck(dev, 0x41, 0x9d);mdelay(1); ++ ++ ++ write_phy_cck(dev, 0x42, 0x15); mdelay(1); ++ write_phy_cck(dev, 0x43, 0x18); mdelay(1); ++ ++ ++ write_phy_cck(dev, 0x44, 0x36); mdelay(1); ++ write_phy_cck(dev, 0x45, 0x35); mdelay(1); ++ write_phy_cck(dev, 0x46, 0x2e); mdelay(1); ++ write_phy_cck(dev, 0x47, 0x25); mdelay(1); ++ write_phy_cck(dev, 0x48, 0x1c); mdelay(1); ++ write_phy_cck(dev, 0x49, 0x12); mdelay(1); ++ write_phy_cck(dev, 0x4a, 0x09); mdelay(1); ++ write_phy_cck(dev, 0x4b, 0x04); mdelay(1); ++ write_phy_cck(dev, 0x4c, 0x5);mdelay(1); ++ ++ ++ write_nic_byte(dev, 0x5b, 0x0d); mdelay(1); ++ ++ ++ ++ // <> ++ // // TESTR 0xb 8187 ++ // write_phy_cck(dev, 0x10, 0x93);// & 0xfb); ++ // ++ // //if(priv->card_type != USB){ ++ // write_phy_ofdm(dev, 0x2, 0x62); ++ // write_phy_ofdm(dev, 0x6, 0x0); ++ // write_phy_ofdm(dev, 0x8, 0x0); ++ // //} ++ ++ rtl8225z2_SetTXPowerLevel(dev, channel); ++ ++ write_phy_cck(dev, 0x10, 0x9b); mdelay(1); /* Rx ant A, 0xdb for B */ ++ write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); /* Rx ant A, 0x10 for B */ ++ ++ rtl8185_tx_antenna(dev, 0x3); /* TX ant A, 0x0 for B */ ++ ++ /* switch to high-speed 3-wire ++ * last digit. 2 for both cck and ofdm ++ */ ++ if(priv->card_type == USB) ++ write_nic_dword(dev, 0x94, 0x3dc00002); ++ else{ ++ write_nic_dword(dev, 0x94, 0x15c00002); ++ rtl8185_rf_pins_enable(dev); ++ } ++ ++ // if(priv->card_type != USB) ++ // rtl8225_set_gain(dev, 4); /* FIXME this '1' is random */ // <> ++ // rtl8225_set_mode(dev, 1); /* FIXME start in B mode */ // <> ++ // ++ // /* make sure is waken up! */ ++ // write_rtl8225(dev,0x4, 0x9ff); ++ // rtl8180_set_anaparam(dev, RTL8225_ANAPARAM_ON); ++ // rtl8185_set_anaparam2(dev, RTL8225_ANAPARAM2_ON); ++ ++ rtl8225_rf_set_chan(dev, priv->chan); ++ ++ //write_nic_word(dev,BRSR,brsr); ++ ++ //rtl8225z2_rf_set_mode(dev); ++ } ++} ++ ++void rtl8225z2_rf_set_mode(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(priv->ieee80211->mode == IEEE_A) ++ { ++ write_rtl8225(dev, 0x5, 0x1865); ++ write_nic_dword(dev, RF_PARA, 0x10084); ++ write_nic_dword(dev, RF_TIMING, 0xa8008); ++ write_phy_ofdm(dev, 0x0, 0x0); ++ write_phy_ofdm(dev, 0xa, 0x6); ++ write_phy_ofdm(dev, 0xb, 0x99); ++ write_phy_ofdm(dev, 0xf, 0x20); ++ write_phy_ofdm(dev, 0x11, 0x7); ++ ++ rtl8225z2_set_gain(dev,4); ++ ++ write_phy_ofdm(dev,0x15, 0x40); ++ write_phy_ofdm(dev,0x17, 0x40); ++ ++ write_nic_dword(dev, 0x94,0x10000000); ++ }else{ ++ ++ write_rtl8225(dev, 0x5, 0x1864); ++ write_nic_dword(dev, RF_PARA, 0x10044); ++ write_nic_dword(dev, RF_TIMING, 0xa8008); ++ write_phy_ofdm(dev, 0x0, 0x1); ++ write_phy_ofdm(dev, 0xa, 0x6); ++ write_phy_ofdm(dev, 0xb, 0x99); ++ write_phy_ofdm(dev, 0xf, 0x20); ++ write_phy_ofdm(dev, 0x11, 0x7); ++ ++ rtl8225z2_set_gain(dev,4); ++ ++ write_phy_ofdm(dev,0x15, 0x40); ++ write_phy_ofdm(dev,0x17, 0x40); ++ ++ write_nic_dword(dev, 0x94,0x04000002); ++ } ++} +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_wx.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_wx.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_wx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_wx.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,2067 @@ ++/* ++ This file contains wireless extension handlers. ++ ++ This is part of rtl8180 OpenSource driver. ++ Copyright (C) Andrea Merello 2004-2005 ++ Released under the terms of GPL (General Public Licence) ++ ++ Parts of this driver are based on the GPL part ++ of the official realtek driver. ++ ++ Parts of this driver are based on the rtl8180 driver skeleton ++ from Patric Schenke & Andres Salomon. ++ ++ Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver. ++ ++ We want to tanks the Authors of those projects and the Ndiswrapper ++ project Authors. ++*/ ++ ++ ++ ++#include "r8187.h" ++#include "r8180_hw.h" ++//added 1117 ++#include "ieee80211/ieee80211.h" ++#ifdef ENABLE_DOT11D ++#include "dot11d.h" ++#endif ++ ++ ++//#define RATE_COUNT 4 ++u32 rtl8180_rates[] = {1000000,2000000,5500000,11000000, ++ 6000000,9000000,12000000,18000000,24000000,36000000,48000000,54000000}; ++#define RATE_COUNT sizeof(rtl8180_rates)/(sizeof(rtl8180_rates[0])) ++ ++#ifdef _RTL8187_EXT_PATCH_ ++#define IW_MODE_MESH 11 ++static int r8180_wx_join_mesh(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++int r8180_wx_set_channel(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++static int r8180_wx_mesh_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++static int r8180_wx_get_mesh_list(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++#endif ++ ++static int r8180_wx_get_freq(struct net_device *dev, ++ struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ return ieee80211_wx_get_freq(priv->ieee80211,a,wrqu,b); ++} ++ ++ ++#if 0 ++ ++static int r8180_wx_set_beaconinterval(struct net_device *dev, struct iw_request_info *aa, ++ union iwreq_data *wrqu, char *b) ++{ ++ int *parms = (int *)b; ++ int bi = parms[0]; ++ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ down(&priv->wx_sem); ++ DMESG("setting beacon interval to %x",bi); ++ ++ priv->ieee80211->beacon_interval=bi; ++ rtl8180_commit(dev); ++ up(&priv->wx_sem); ++ ++ return 0; ++} ++ ++ ++static int r8180_wx_set_forceassociate(struct net_device *dev, struct iw_request_info *aa, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv=ieee80211_priv(dev); ++ int *parms = (int *)extra; ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ priv->ieee80211->force_associate = (parms[0] > 0); ++ ++ ++ return 0; ++} ++ ++#endif ++static int r8180_wx_get_mode(struct net_device *dev, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b) ++{ ++ struct r8180_priv *priv=ieee80211_priv(dev); ++ ++ return ieee80211_wx_get_mode(priv->ieee80211,a,wrqu,b); ++} ++ ++ ++ ++static int r8180_wx_get_rate(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ return ieee80211_wx_get_rate(priv->ieee80211,info,wrqu,extra); ++} ++ ++ ++ ++static int r8180_wx_set_rate(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ int ret; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ down(&priv->wx_sem); ++ ++ ret = ieee80211_wx_set_rate(priv->ieee80211,info,wrqu,extra); ++ ++ up(&priv->wx_sem); ++ ++ return ret; ++} ++#ifdef JOHN_IOCTL ++u16 read_rtl8225(struct net_device *dev, u8 addr); ++void write_rtl8225(struct net_device *dev, u8 adr, u16 data); ++u32 john_read_rtl8225(struct net_device *dev, u8 adr); ++void _write_rtl8225(struct net_device *dev, u8 adr, u16 data); ++ ++static int r8180_wx_read_regs(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u8 addr = 0; ++ u16 data1; ++ ++ down(&priv->wx_sem); ++ ++ ++ get_user(addr,(u8*)wrqu->data.pointer); ++ data1 = read_rtl8225(dev, addr); ++ wrqu->data.length = data1; ++ ++ up(&priv->wx_sem); ++ return 0; ++ ++} ++ ++static int r8180_wx_write_regs(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u8 addr = 0; ++ ++ down(&priv->wx_sem); ++ ++ get_user(addr, (u8*)wrqu->data.pointer); ++ write_rtl8225(dev, addr, wrqu->data.length); ++ ++ up(&priv->wx_sem); ++ return 0; ++ ++} ++ ++void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data); ++u8 rtl8187_read_phy(struct net_device *dev,u8 adr, u32 data); ++ ++static int r8180_wx_read_bb(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u8 databb; ++#if 0 ++ int i; ++ for(i=0;i<12;i++) printk("%8x\n", read_cam(dev, i) ); ++#endif ++ ++ down(&priv->wx_sem); ++ ++ databb = rtl8187_read_phy(dev, (u8)wrqu->data.length, 0x00000000); ++ wrqu->data.length = databb; ++ ++ up(&priv->wx_sem); ++ return 0; ++} ++ ++void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data); ++static int r8180_wx_write_bb(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u8 databb = 0; ++ ++ down(&priv->wx_sem); ++ ++ get_user(databb, (u8*)wrqu->data.pointer); ++ rtl8187_write_phy(dev, wrqu->data.length, databb); ++ ++ up(&priv->wx_sem); ++ return 0; ++ ++} ++ ++ ++static int r8180_wx_write_nicb(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u32 addr = 0; ++ ++ down(&priv->wx_sem); ++ ++ get_user(addr, (u32*)wrqu->data.pointer); ++ write_nic_byte(dev, addr, wrqu->data.length); ++ ++ up(&priv->wx_sem); ++ return 0; ++ ++} ++static int r8180_wx_read_nicb(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u32 addr = 0; ++ u16 data1; ++ ++ down(&priv->wx_sem); ++ ++ get_user(addr,(u32*)wrqu->data.pointer); ++ data1 = read_nic_byte(dev, addr); ++ wrqu->data.length = data1; ++ ++ up(&priv->wx_sem); ++ return 0; ++} ++ ++static inline int is_same_network(struct ieee80211_network *src, ++ struct ieee80211_network *dst, ++ struct ieee80211_device *ieee) ++{ ++ /* A network is only a duplicate if the channel, BSSID, ESSID ++ * and the capability field (in particular IBSS and BSS) all match. ++ * We treat all with the same BSSID and channel ++ * as one network */ ++ return (((src->ssid_len == dst->ssid_len)||(ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod, 080819,for hidden ap ++ //((src->ssid_len == dst->ssid_len) && ++ (src->channel == dst->channel) && ++ !memcmp(src->bssid, dst->bssid, ETH_ALEN) && ++ (!memcmp(src->ssid, dst->ssid, src->ssid_len)||(ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod, 080819,for hidden ap ++ //!memcmp(src->ssid, dst->ssid, src->ssid_len) && ++ ((src->capability & WLAN_CAPABILITY_IBSS) == ++ (dst->capability & WLAN_CAPABILITY_IBSS)) && ++ ((src->capability & WLAN_CAPABILITY_BSS) == ++ (dst->capability & WLAN_CAPABILITY_BSS))); ++} ++ ++static int r8180_wx_get_ap_status(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ struct ieee80211_device *ieee = priv->ieee80211; ++ struct ieee80211_network *target; ++ int name_len; ++ ++ down(&priv->wx_sem); ++ ++ //count the length of input ssid ++ for(name_len=0 ; ((char*)wrqu->data.pointer)[name_len]!='\0' ; name_len++); ++ ++ //search for the correspoding info which is received ++ list_for_each_entry(target, &ieee->network_list, list) { ++ if ( (target->ssid_len == name_len) && ++ (strncmp(target->ssid, (char*)wrqu->data.pointer, name_len)==0)){ ++ if( ((jiffies-target->last_scanned)/HZ > 1) && (ieee->state == IEEE80211_LINKED) && (is_same_network(&ieee->current_network,target, ieee)) ) ++ wrqu->data.length = 999; ++ else ++ wrqu->data.length = target->SignalStrength; ++ if(target->wpa_ie_len>0 || target->rsn_ie_len>0 ) ++ //set flags=1 to indicate this ap is WPA ++ wrqu->data.flags = 1; ++ else wrqu->data.flags = 0; ++ ++ ++ break; ++ } ++ } ++ ++ if (&target->list == &ieee->network_list){ ++ wrqu->data.flags = 3; ++ } ++ up(&priv->wx_sem); ++ return 0; ++} ++ ++ ++ ++#endif ++ ++static int r8180_wx_set_rawtx(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int ret; ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ down(&priv->wx_sem); ++ ++ ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra); ++ ++ up(&priv->wx_sem); ++ ++ return ret; ++ ++} ++ ++static int r8180_wx_set_crcmon(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int *parms = (int *)extra; ++ int enable = (parms[0] > 0); ++ short prev = priv->crcmon; ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ down(&priv->wx_sem); ++ ++ if(enable) ++ priv->crcmon=1; ++ else ++ priv->crcmon=0; ++ ++ DMESG("bad CRC in monitor mode are %s", ++ priv->crcmon ? "accepted" : "rejected"); ++ ++ if(prev != priv->crcmon && priv->up){ ++ rtl8180_down(dev); ++ rtl8180_up(dev); ++ } ++ ++ up(&priv->wx_sem); ++ ++ return 0; ++} ++ ++static int r8180_wx_set_mode(struct net_device *dev, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int ret; ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if (priv->mshobj && (priv->ieee80211->iw_ext_mode==11)) return 0; ++#endif ++ down(&priv->wx_sem); ++ ++#ifdef CONFIG_IPS ++ if(priv->bInactivePs){ ++ if(wrqu->mode != IW_MODE_INFRA){ ++ down(&priv->ieee80211->ips_sem); ++ IPSLeave(dev); ++ up(&priv->ieee80211->ips_sem); ++ } ++ } ++#endif ++ ret = ieee80211_wx_set_mode(priv->ieee80211,a,wrqu,b); ++ ++ rtl8187_set_rxconf(dev); ++ ++ up(&priv->wx_sem); ++ return ret; ++} ++ ++ ++//YJ,add,080819,for hidden ap ++struct iw_range_with_scan_capa ++{ ++ /* Informative stuff (to choose between different interface) */ ++ __u32 throughput; /* To give an idea... */ ++ /* In theory this value should be the maximum benchmarked ++ * TCP/IP throughput, because with most of these devices the ++ * bit rate is meaningless (overhead an co) to estimate how ++ * fast the connection will go and pick the fastest one. ++ * I suggest people to play with Netperf or any benchmark... ++ */ ++ ++ /* NWID (or domain id) */ ++ __u32 min_nwid; /* Minimal NWID we are able to set */ ++ __u32 max_nwid; /* Maximal NWID we are able to set */ ++ ++ /* Old Frequency (backward compat - moved lower ) */ ++ __u16 old_num_channels; ++ __u8 old_num_frequency; ++ ++ /* Scan capabilities */ ++ __u8 scan_capa; ++}; ++//YJ,add,080819,for hidden ap ++ ++static int rtl8180_wx_get_range(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct iw_range *range = (struct iw_range *)extra; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u16 val; ++ int i; ++ struct iw_range_with_scan_capa* tmp = (struct iw_range_with_scan_capa*)range; //YJ,add,080819,for hidden ap ++ ++ wrqu->data.length = sizeof(*range); ++ memset(range, 0, sizeof(*range)); ++ ++ /* Let's try to keep this struct in the same order as in ++ * linux/include/wireless.h ++ */ ++ ++ /* TODO: See what values we can set, and remove the ones we can't ++ * set, or fill them with some default data. ++ */ ++ ++ /* ~5 Mb/s real (802.11b) */ ++ range->throughput = 5 * 1000 * 1000; ++ ++ // TODO: Not used in 802.11b? ++// range->min_nwid; /* Minimal NWID we are able to set */ ++ // TODO: Not used in 802.11b? ++// range->max_nwid; /* Maximal NWID we are able to set */ ++ ++ /* Old Frequency (backward compat - moved lower ) */ ++// range->old_num_channels; ++// range->old_num_frequency; ++// range->old_freq[6]; /* Filler to keep "version" at the same offset */ ++ if(priv->rf_set_sens != NULL) ++ range->sensitivity = priv->max_sens; /* signal level threshold range */ ++ ++ range->max_qual.qual = 100; ++ /* TODO: Find real max RSSI and stick here */ ++ range->max_qual.level = 0; ++ range->max_qual.noise = -98; ++ range->max_qual.updated = 7; /* Updated all three */ ++ ++ range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ ++ /* TODO: Find real 'good' to 'bad' threshol value for RSSI */ ++ range->avg_qual.level = 20 + -98; ++ range->avg_qual.noise = 0; ++ range->avg_qual.updated = 7; /* Updated all three */ ++ ++ range->num_bitrates = RATE_COUNT; ++ ++ for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) { ++ range->bitrate[i] = rtl8180_rates[i]; ++ } ++ ++ range->min_frag = MIN_FRAG_THRESHOLD; ++ range->max_frag = MAX_FRAG_THRESHOLD; ++ ++ range->pm_capa = 0; ++ ++ range->we_version_compiled = WIRELESS_EXT; ++ range->we_version_source = 16; ++ ++// range->retry_capa; /* What retry options are supported */ ++// range->retry_flags; /* How to decode max/min retry limit */ ++// range->r_time_flags; /* How to decode max/min retry life */ ++// range->min_retry; /* Minimal number of retries */ ++// range->max_retry; /* Maximal number of retries */ ++// range->min_r_time; /* Minimal retry lifetime */ ++// range->max_r_time; /* Maximal retry lifetime */ ++ ++ range->num_channels = 14; ++ ++ for (i = 0, val = 0; i < 14; i++) { ++ ++ // Include only legal frequencies for some countries ++#ifdef ENABLE_DOT11D ++ if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) { ++#else ++ if ((priv->ieee80211->channel_map)[i+1]) { ++#endif ++ range->freq[val].i = i + 1; ++ range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000; ++ range->freq[val].e = 1; ++ val++; ++ } else { ++ // FIXME: do we need to set anything for channels ++ // we don't use ? ++ } ++ ++ if (val == IW_MAX_FREQUENCIES) ++ break; ++ } ++ ++ range->num_frequency = val; ++ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | ++ IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; ++ ++ tmp->scan_capa = 0x01; //YJ,add,080819,for hidden ap ++ ++ return 0; ++} ++ ++ ++static int r8180_wx_set_scan(struct net_device *dev, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ struct ieee80211_device* ieee = priv->ieee80211; ++ int ret; ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ //printk("==============>%s()\n",__FUNCTION__); ++ if(!priv->up) ++ return -1; ++ ++ if (wrqu->data.flags & IW_SCAN_THIS_ESSID) ++ { ++ struct iw_scan_req* req = (struct iw_scan_req*)b; ++ if (req->essid_len) ++ { ++ ieee->current_network.ssid_len = req->essid_len; ++ memcpy(ieee->current_network.ssid, req->essid, req->essid_len); ++ } ++ } ++ ++ //set Tr switch to hardware control to scan more bss ++ if(priv->TrSwitchState == TR_SW_TX) { ++ //YJ,add,080611 ++ write_nic_byte(dev, RFPinsSelect, (u8)(priv->wMacRegRfPinsSelect)); ++ write_nic_byte(dev, RFPinsOutput, (u8)(priv->wMacRegRfPinsOutput)); ++ //YJ,add,080611,end ++ priv->TrSwitchState = TR_HW_CONTROLLED; ++ } ++#ifdef _RTL8187_EXT_PATCH_ ++ if((priv->ieee80211->iw_mode == IW_MODE_MESH) && (priv->ieee80211->iw_ext_mode == IW_MODE_MESH)){ ++ r8180_wx_mesh_scan(dev,a,wrqu,b); ++ ret = 0; ++ } ++ else ++#endif ++ { ++ down(&priv->wx_sem); ++ if(priv->ieee80211->state != IEEE80211_LINKED){ ++ //printk("===>start no link scan\n"); ++ //ieee80211_start_scan(priv->ieee80211); ++ //lzm mod 090115 because wq can't scan complete once ++ //because after start protocal wq scan is in doing ++ //so we should stop it first. ++ ieee80211_stop_scan(priv->ieee80211); ++ ieee80211_start_scan_syncro(priv->ieee80211); ++ ret = 0; ++ } else { ++ ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b); ++ } ++ up(&priv->wx_sem); ++ } ++ return ret; ++} ++ ++ ++static int r8180_wx_get_scan(struct net_device *dev, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b) ++{ ++ ++ int ret; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(!priv->up) return -1; ++#ifdef _RTL8187_EXT_PATCH_ ++ if((priv->ieee80211->iw_mode == IW_MODE_MESH) && (priv->ieee80211->iw_ext_mode == IW_MODE_MESH)){ ++ ret = r8180_wx_get_mesh_list(dev, a, wrqu, b); ++ } ++ else ++#endif ++ { ++ down(&priv->wx_sem); ++ ++ ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b); ++ ++ up(&priv->wx_sem); ++ } ++ return ret; ++} ++ ++ ++static int r8180_wx_set_essid(struct net_device *dev, ++ struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int ret; ++#ifdef _RTL8187_EXT_PATCH_ ++ struct ieee80211_device *ieee = priv->ieee80211; ++ char ch = 0; ++ char tmpmeshid[32]; ++ char *p; ++ int tmpmeshid_len=0; ++ int i; ++ short proto_started; ++#endif ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ //printk("==========>%s()\n",__FUNCTION__); ++ down(&priv->wx_sem); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if((priv->ieee80211->iw_mode == IW_MODE_MESH) && (priv->ieee80211->iw_ext_mode == IW_MODE_MESH)){ ++ if (wrqu->essid.length > IW_ESSID_MAX_SIZE){ ++ ret= -E2BIG; ++ goto out; ++ } ++ if (wrqu->essid.flags && (wrqu->essid.length > 1)) { ++ memset(tmpmeshid,0,32); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ tmpmeshid_len=wrqu->essid.length; ++#else ++ tmpmeshid_len=wrqu->essid.length + 1; ++#endif ++ p=b+tmpmeshid_len-2; ++ for(i=tmpmeshid_len-1;i>0;i--) ++ { ++ if((*p)=='@') ++ break; ++ p--; ++ } ++ if((i == 0) || (i == 1)){ ++ printk("error:wrong meshid\n"); ++ ret = -1; ++ goto out; ++ } ++ ++ memcpy(tmpmeshid,b,(i-1)); ++ p++; ++ if((tmpmeshid_len-1-i)==1) ++ { ++ if(*p > '9'|| *p <= '0'){ ++ goto out; ++ } else { ++ ch = *p - '0'; ++ } ++ } ++ else if((tmpmeshid_len-1-i)==2) ++ { ++ if((*p == '1') && (*(p+1) >= '0') && (*(p+1) <= '9')) ++ ch = (*p - '0') * 10 + (*(p+1) - '0'); ++ else ++ goto out; ++ } ++ else { ++ ret = 0; ++ goto out; ++ } ++ if(ch > 14) ++ { ++ ret = 0; ++ printk("channel is invalid: %d\n",ch); ++ goto out; ++ } ++ ieee->sync_scan_hurryup = 1; ++ ++ proto_started = ieee->proto_started; ++ if(proto_started) ++ ieee80211_stop_protocol(ieee); ++ ++ printk("==============>tmpmeshid is %s\n",tmpmeshid); ++ priv->mshobj->ext_patch_r8180_wx_set_meshID(dev, tmpmeshid); ++ priv->mshobj->ext_patch_r8180_wx_set_mesh_chan(dev,ch); ++ r8180_wx_set_channel(dev, NULL, NULL, &ch); ++ if (proto_started) ++ ieee80211_start_protocol(ieee); ++ } ++ else{ ++ printk("BUG:meshid is null\n"); ++ ret=0; ++ goto out; ++ } ++ ++ ret = 0; ++ } ++ else ++#endif ++ { ++ ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b); ++ } ++ ++#ifdef _RTL8187_EXT_PATCH_ ++out: ++#endif ++ up(&priv->wx_sem); ++ return ret; ++} ++ ++ ++static int r8180_wx_get_essid(struct net_device *dev, ++ struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b) ++{ ++ int ret; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ down(&priv->wx_sem); ++ ++ ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b); ++ ++ up(&priv->wx_sem); ++ ++ return ret; ++} ++ ++ ++static int r8180_wx_set_freq(struct net_device *dev, struct iw_request_info *a, ++ union iwreq_data *wrqu, char *b) ++{ ++ int ret; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ down(&priv->wx_sem); ++ ++ ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b); ++ ++ up(&priv->wx_sem); ++ return ret; ++} ++ ++static int r8180_wx_get_name(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra); ++} ++ ++ ++static int r8180_wx_set_frag(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ if (wrqu->frag.disabled) ++ priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD; ++ else { ++ if (wrqu->frag.value < MIN_FRAG_THRESHOLD || ++ wrqu->frag.value > MAX_FRAG_THRESHOLD) ++ return -EINVAL; ++ ++ priv->ieee80211->fts = wrqu->frag.value & ~0x1; ++ } ++ ++ return 0; ++} ++ ++ ++static int r8180_wx_get_frag(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ wrqu->frag.value = priv->ieee80211->fts; ++ wrqu->frag.fixed = 0; /* no auto select */ ++ wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); ++ ++ return 0; ++} ++ ++ ++static int r8180_wx_set_wap(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *awrq, ++ char *extra) ++{ ++ int ret; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ //printk("in function %s\n",__FUNCTION__); ++#ifdef _RTL8187_EXT_PATCH_ ++ if (priv->mshobj && (priv->ieee80211->iw_ext_mode==11)){ ++ return 0; ++ } ++#endif ++ down(&priv->wx_sem); ++ ++ ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra); ++ ++ up(&priv->wx_sem); ++ return ret; ++ ++} ++ ++ ++static int r8180_wx_get_wap(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra); ++} ++ ++ ++static int r8180_wx_get_enc(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *key) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key); ++} ++ ++static int r8180_wx_set_enc(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *key) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int ret; ++#ifdef JOHN_HWSEC ++// struct ieee80211_device *ieee = priv->ieee80211; ++// u32 TargetContent; ++ u32 hwkey[4]={0,0,0,0}; ++ u8 mask=0xff; ++ u32 key_idx=0; ++ u8 broadcast_addr[6] ={ 0xff,0xff,0xff,0xff,0xff,0xff}; ++ u8 zero_addr[4][6] ={ {0x00,0x00,0x00,0x00,0x00,0x00}, ++ {0x00,0x00,0x00,0x00,0x00,0x01}, ++ {0x00,0x00,0x00,0x00,0x00,0x02}, ++ {0x00,0x00,0x00,0x00,0x00,0x03} }; ++ int i; ++ ++#endif ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ down(&priv->wx_sem); ++ ++ DMESG("Setting SW wep key"); ++ ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key); ++ ++ up(&priv->wx_sem); ++ ++#ifdef JOHN_HWSEC ++ ++ //sometimes, the length is zero while we do not type key value ++ if(wrqu->encoding.length!=0){ ++ ++ for(i=0 ; i<4 ; i++){ ++ hwkey[i] |= key[4*i+0]&mask; ++ if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00; ++ if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00; ++ hwkey[i] |= (key[4*i+1]&mask)<<8; ++ hwkey[i] |= (key[4*i+2]&mask)<<16; ++ hwkey[i] |= (key[4*i+3]&mask)<<24; ++ } ++ ++ #define CONF_WEP40 0x4 ++ #define CONF_WEP104 0x14 ++ ++ switch(wrqu->encoding.flags){ ++ case 0: ++ case 1: key_idx = 0; break; ++ case 2: key_idx = 1; break; ++ case 3: key_idx = 2; break; ++ case 4: key_idx = 3; break; ++ default: break; ++ } ++ ++ if(wrqu->encoding.length==0x5){ ++ setKey( dev, ++ key_idx, //EntryNo ++ key_idx, //KeyIndex ++ KEY_TYPE_WEP40, //KeyType ++ zero_addr[key_idx], ++ 0, //DefaultKey ++ hwkey); //KeyContent ++ ++ if(key_idx == 0){ ++ ++ write_nic_byte(dev, WPA_CONFIG, 7); ++ ++ setKey( dev, ++ 4, //EntryNo ++ key_idx, //KeyIndex ++ KEY_TYPE_WEP40, //KeyType ++ broadcast_addr, //addr ++ 0, //DefaultKey ++ hwkey); //KeyContent ++ } ++ } ++ ++ else if(wrqu->encoding.length==0xd){ ++ setKey( dev, ++ key_idx, //EntryNo ++ key_idx, //KeyIndex ++ KEY_TYPE_WEP104, //KeyType ++ zero_addr[key_idx], ++ 0, //DefaultKey ++ hwkey); //KeyContent ++ ++ if(key_idx == 0){ ++ ++ write_nic_byte(dev, WPA_CONFIG, 7); ++ ++ setKey( dev, ++ 4, //EntryNo ++ key_idx, //KeyIndex ++ KEY_TYPE_WEP104, //KeyType ++ broadcast_addr, //addr ++ 0, //DefaultKey ++ hwkey); //KeyContent ++ } ++ } ++ else printk("wrong type in WEP, not WEP40 and WEP104\n"); ++ ++ } ++ ++ //consider the setting different key index situation ++ //wrqu->encoding.flags = 801 means that we set key with index "1" ++ if(wrqu->encoding.length==0 && (wrqu->encoding.flags >>8) == 0x8 ){ ++ ++ write_nic_byte(dev, WPA_CONFIG, 7); ++ ++ //copy wpa config from default key(key0~key3) to broadcast key(key5) ++ // ++ key_idx = (wrqu->encoding.flags & 0xf)-1 ; ++ write_cam(dev, (4*6), 0xffff0000|read_cam(dev, key_idx*6) ); ++ write_cam(dev, (4*6)+1, 0xffffffff); ++ write_cam(dev, (4*6)+2, read_cam(dev, (key_idx*6)+2) ); ++ write_cam(dev, (4*6)+3, read_cam(dev, (key_idx*6)+3) ); ++ write_cam(dev, (4*6)+4, read_cam(dev, (key_idx*6)+4) ); ++ write_cam(dev, (4*6)+5, read_cam(dev, (key_idx*6)+5) ); ++ } ++ ++#endif /*JOHN_HWSEC*/ ++ return ret; ++} ++ ++ ++static int r8180_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union ++ iwreq_data *wrqu, char *p){ ++ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int *parms=(int*)p; ++ int mode=parms[0]; ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ priv->ieee80211->active_scan = mode; ++ ++ return 1; ++} ++ ++ ++ ++static int r8180_wx_set_retry(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int err = 0; ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ down(&priv->wx_sem); ++ ++ if (wrqu->retry.flags & IW_RETRY_LIFETIME || ++ wrqu->retry.disabled){ ++ err = -EINVAL; ++ goto exit; ++ } ++ if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){ ++ err = -EINVAL; ++ goto exit; ++ } ++ ++ if(wrqu->retry.value > R8180_MAX_RETRY){ ++ err= -EINVAL; ++ goto exit; ++ } ++ if (wrqu->retry.flags & IW_RETRY_MAX) { ++ priv->retry_rts = wrqu->retry.value; ++ DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value); ++ ++ }else { ++ priv->retry_data = wrqu->retry.value; ++ DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value); ++ } ++ ++ /* FIXME ! ++ * We might try to write directly the TX config register ++ * or to restart just the (R)TX process. ++ * I'm unsure if whole reset is really needed ++ */ ++ ++ rtl8180_commit(dev); ++ /* ++ if(priv->up){ ++ rtl8180_rtx_disable(dev); ++ rtl8180_rx_enable(dev); ++ rtl8180_tx_enable(dev); ++ ++ } ++ */ ++exit: ++ up(&priv->wx_sem); ++ ++ return err; ++} ++ ++static int r8180_wx_get_retry(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ ++ wrqu->retry.disabled = 0; /* can't be disabled */ ++ ++ if ((wrqu->retry.flags & IW_RETRY_TYPE) == ++ IW_RETRY_LIFETIME) ++ return -EINVAL; ++ ++ if (wrqu->retry.flags & IW_RETRY_MAX) { ++ wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX; ++ wrqu->retry.value = priv->retry_rts; ++ } else { ++ wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN; ++ wrqu->retry.value = priv->retry_data; ++ } ++ //DMESG("returning %d",wrqu->retry.value); ++ ++ ++ return 0; ++} ++ ++static int r8180_wx_get_sens(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ if(priv->rf_set_sens == NULL) ++ return -1; /* we have not this support for this radio */ ++ wrqu->sens.value = priv->sens; ++ return 0; ++} ++ ++ ++static int r8180_wx_set_sens(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ short err = 0; ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ down(&priv->wx_sem); ++ //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value); ++ if(priv->rf_set_sens == NULL) { ++ err= -1; /* we have not this support for this radio */ ++ goto exit; ++ } ++ if(priv->rf_set_sens(dev, wrqu->sens.value) == 0) ++ priv->sens = wrqu->sens.value; ++ else ++ err= -EINVAL; ++ ++exit: ++ up(&priv->wx_sem); ++ ++ return err; ++} ++ ++ ++static int dummy(struct net_device *dev, struct iw_request_info *a, ++ union iwreq_data *wrqu,char *b) ++{ ++ return -1; ++} ++static int r8180_wx_set_enc_ext(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ //printk("===>%s()\n", __FUNCTION__); ++ ++ int ret=0; ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ down(&priv->wx_sem); ++ ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra); ++ up(&priv->wx_sem); ++ return ret; ++ ++} ++static int r8180_wx_set_auth(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data* data, char *extra) ++{ ++ //printk("====>%s()\n", __FUNCTION__); ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int ret=0; ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ down(&priv->wx_sem); ++ ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra); ++ up(&priv->wx_sem); ++ return ret; ++} ++ ++static int r8180_wx_set_mlme(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ //printk("====>%s()\n", __FUNCTION__); ++ ++ int ret=0; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ down(&priv->wx_sem); ++#if 1 ++ ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra); ++#endif ++ up(&priv->wx_sem); ++ return ret; ++} ++ ++static int r8180_wx_set_gen_ie(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data* data, char *extra) ++{ ++ //printk("====>%s(), len:%d\n", __FUNCTION__, data->length); ++ int ret=0; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ down(&priv->wx_sem); ++#if 1 ++ ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length); ++#endif ++ up(&priv->wx_sem); ++ //printk("<======%s(), ret:%d\n", __FUNCTION__, ret); ++ return ret; ++ ++ ++} ++ ++#ifdef _RTL8187_EXT_PATCH_ ++/* ++ Output: ++ (case 1) Mesh: Enable. MESHID=[%s] (max length of %s is 32 bytes). ++ (case 2) Mesh: Disable. ++*/ ++static int r8180_wx_get_meshinfo(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if( ! priv->mshobj || !priv->mshobj->ext_patch_r8180_wx_get_meshinfo ) ++ return 0; ++ return priv->mshobj->ext_patch_r8180_wx_get_meshinfo(dev, info, wrqu, extra); ++} ++ ++ ++static int r8180_wx_enable_mesh(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ struct ieee80211_device *ieee = priv->ieee80211; ++ ++ int ret = 0; ++ ++ if( ! priv->mshobj || !priv->mshobj->ext_patch_r8180_wx_enable_mesh ) ++ return 0; ++ ++ down(&priv->wx_sem); ++ if(priv->mshobj->ext_patch_r8180_wx_enable_mesh(dev)) ++ { ++ union iwreq_data tmprqu; ++ tmprqu.mode = ieee->iw_mode; ++ ieee->iw_mode = 0; ++ ret = ieee80211_wx_set_mode(ieee, info, &tmprqu, extra); ++ rtl8187_set_rxconf(dev); ++ } ++ ++ up(&priv->wx_sem); ++ ++ return ret; ++ ++} ++ ++static int r8180_wx_disable_mesh(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ struct ieee80211_device *ieee = priv->ieee80211; ++ ++ int ret = 0; ++ ++ if( ! priv->mshobj || !priv->mshobj->ext_patch_r8180_wx_disable_mesh ) ++ return 0; ++ ++ down(&priv->wx_sem); ++ if(priv->mshobj->ext_patch_r8180_wx_disable_mesh(dev)) ++ { ++ union iwreq_data tmprqu; ++ tmprqu.mode = ieee->iw_mode; ++ ieee->iw_mode = 999; ++ ret = ieee80211_wx_set_mode(ieee, info, &tmprqu, extra); ++ rtl8187_set_rxconf(dev); ++ } ++ ++ up(&priv->wx_sem); ++ ++ return ret; ++} ++ ++ ++int r8180_wx_set_channel(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ int ch = *extra; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ struct ieee80211_device *ieee = priv->ieee80211; ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ // is 11s ? ++ if (!priv->mshobj || (ieee->iw_mode != ieee->iw_ext_mode) || !priv->mshobj->ext_patch_r8180_wx_set_channel ) ++ return 0; ++ ++ printk("set channel = %d\n", ch); ++ if ( ch < 0 ) ++ { ++ ieee80211_start_scan(ieee); // auto ++ ieee->meshScanMode =2; ++ } ++ else ++ { ++//#ifdef NETWORKMANAGER_UI ++ if((priv->ieee80211->iw_mode == IW_MODE_MESH) && (priv->ieee80211->iw_ext_mode == IW_MODE_MESH)){ ++ } ++//#else ++ else{ ++ down(&priv->wx_sem);} ++//#endif ++ ieee->meshScanMode =0; ++ // ieee->set_chan(dev, ch); ++//#ifdef _RTL8187_EXT_PATCH_ ++ if(priv->mshobj->ext_patch_r8180_wx_set_channel) ++ { ++ priv->mshobj->ext_patch_r8180_wx_set_channel(ieee, ch); ++ priv->mshobj->ext_patch_r8180_wx_set_mesh_chan(dev,ch); ++ } ++//#endif ++ ieee->set_chan(ieee->dev, ch); ++ ieee->current_network.channel = ch; ++ queue_work(ieee->wq, &ieee->ext_stop_scan_wq); ++ ieee80211_ext_send_11s_beacon(ieee); ++//#ifdef NETWORKMANAGER_UI ++ if((priv->ieee80211->iw_mode == IW_MODE_MESH) && (priv->ieee80211->iw_ext_mode == IW_MODE_MESH)){ ++ } ++//#else ++ else{ ++ up(&priv->wx_sem);} ++//#endif ++ //up(&ieee->wx_sem); ++ ++ // ieee80211_stop_scan(ieee); // user set ++ // ++ ++ /* ++ netif_carrier_off(ieee->dev); ++ ++ if (ieee->data_hard_stop) ++ ieee->data_hard_stop(ieee->dev); ++ ++ ieee->state = IEEE80211_NOLINK; ++ ieee->link_change(ieee->dev); ++ ++ ieee->current_network.channel = fwrq->m; ++ ieee->set_chan(ieee->dev, ieee->current_network.channel); ++ ++ ++ if (ieee->data_hard_resume) ++ ieee->data_hard_resume(ieee->dev); ++ ++ netif_carrier_on(ieee->dev); ++ */ ++ ++ } ++ ++ return 0; ++} ++ ++static int r8180_wx_set_meshID(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ if( ! priv->mshobj || !priv->mshobj->ext_patch_r8180_wx_set_meshID ) ++ return 0; ++ ++ //printk("len=%d\n", wrqu->data.length); ++ //printk("\nCall setMeshid."); ++ return priv->mshobj->ext_patch_r8180_wx_set_meshID(dev, wrqu->data.pointer); ++} ++ ++ ++/* reserved for future ++static int r8180_wx_add_mac_allow(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if( ! priv->mshobj || !priv->mshobj->ext_patch_r8180_wx_set_add_mac_allow ) ++ return 0; ++ ++ return priv->mshobj->ext_patch_r8180_wx_set_add_mac_allow(dev, info, wrqu, extra); ++} ++ ++static int r8180_wx_del_mac_allow(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if( ! priv->mshobj || !priv->mshobj->ext_patch_r8180_wx_set_del_mac_allow ) ++ return 0; ++ ++ return priv->mshobj->ext_patch_r8180_wx_set_del_mac_allow(dev, info, wrqu, extra); ++} ++*/ ++static int r8180_wx_add_mac_deny(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if( ! priv->mshobj || !priv->mshobj->ext_patch_r8180_wx_set_add_mac_deny ) ++ return 0; ++ ++ return priv->mshobj->ext_patch_r8180_wx_set_add_mac_deny(dev, info, wrqu, extra); ++} ++ ++static int r8180_wx_del_mac_deny(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if( ! priv->mshobj || !priv->mshobj->ext_patch_r8180_wx_set_del_mac_deny ) ++ return 0; ++ ++ return priv->mshobj->ext_patch_r8180_wx_set_del_mac_deny(dev, info, wrqu, extra); ++} ++ ++/* reserved for future ++static int r8180_wx_get_mac_allow(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if( ! priv->mshobj || !priv->mshobj->ext_patch_r8180_wx_get_mac_allow ) ++ return 0; ++ ++ return priv->mshobj->ext_patch_r8180_wx_get_mac_allow(dev, info, wrqu, extra); ++} ++*/ ++ ++static int r8180_wx_get_mac_deny(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if( ! priv->mshobj || !priv->mshobj->ext_patch_r8180_wx_get_mac_deny ) ++ return 0; ++ ++ return priv->mshobj->ext_patch_r8180_wx_get_mac_deny(dev, info, wrqu, extra); ++} ++ ++ ++static int r8180_wx_get_mesh_list(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if( ! priv->mshobj || !priv->mshobj->ext_patch_r8180_wx_get_mesh_list ) ++ return 0; ++ ++ return priv->mshobj->ext_patch_r8180_wx_get_mesh_list(dev, info, wrqu, extra); ++} ++ ++static int r8180_wx_mesh_scan(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if( ! priv->mshobj || !priv->mshobj->ext_patch_r8180_wx_mesh_scan ) ++ return 0; ++ ++ return priv->mshobj->ext_patch_r8180_wx_mesh_scan(dev, info, wrqu, extra); ++} ++ ++static int r8180_wx_join_mesh(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int index; ++ int ret=0; ++ char extmeshid[32]; ++ int len=0; ++ char id[50], ch; ++//#ifdef NETWORKMANAGER_UI ++ ++ if((priv->ieee80211->iw_mode == IW_MODE_MESH) && (priv->ieee80211->iw_ext_mode == IW_MODE_MESH)){ ++ printk("join mesh %s\n",extra); ++ if (wrqu->essid.length > IW_ESSID_MAX_SIZE){ ++ ret= -E2BIG; ++ goto out; ++ } ++ //printk("wrqu->essid.length is %d\n",wrqu->essid.length); ++ //printk("wrqu->essid.flags is %d\n",wrqu->essid.flags); ++ if((wrqu->essid.length == 1) && (wrqu->essid.flags == 1)){ ++ ret = 0; ++ goto out; ++ } ++ if (wrqu->essid.flags && wrqu->essid.length) { ++ if(priv->mshobj->ext_patch_r8180_wx_get_selected_mesh_channel(dev, extra, &ch)) ++ { ++ priv->mshobj->ext_patch_r8180_wx_set_meshID(dev, extra); ++ priv->mshobj->ext_patch_r8180_wx_set_mesh_chan(dev,ch); ++ r8180_wx_set_channel(dev, NULL, NULL, &ch); ++ } ++ else ++ printk("invalid mesh #\n"); ++ ++ } ++#if 0 ++ else{ ++ if(priv->mshobj->ext_patch_r8180_wx_get_selected_mesh_channel(dev, 0, &ch)) ++ { ++ priv->mshobj->ext_patch_r8180_wx_set_meshID(dev, extra); ++ priv->mshobj->ext_patch_r8180_wx_set_mesh_chan(dev,ch); ++ r8180_wx_set_channel(dev, NULL, NULL, &ch); ++ } ++ else ++ printk("invalid mesh #\n"); ++ ++ } ++#endif ++ } ++ else{ ++//#else ++ index = *(extra); ++// printk("index=%d\n", index); ++ ++ if( ! priv->mshobj ++ || !priv->mshobj->ext_patch_r8180_wx_set_meshID ++ || !priv->mshobj->ext_patch_r8180_wx_get_selected_mesh ) ++ return 0; ++ ++ if( priv->mshobj->ext_patch_r8180_wx_get_selected_mesh(dev, index, &ch, id) ) ++ { ++ // printk("ch=%d, id=%s\n", ch, id); ++ priv->mshobj->ext_patch_r8180_wx_set_meshID(dev, id); ++ priv->mshobj->ext_patch_r8180_wx_set_mesh_chan(dev,ch); ++ r8180_wx_set_channel(dev, NULL, NULL, &ch); ++ } ++ else ++ printk("invalid mesh #\n"); ++ } ++//#endif ++out: ++ return ret; ++} ++ ++#endif // _RTL8187_EXT_PATCH_ ++ ++ ++static int r8180_wx_get_radion(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++// u8 addr; ++ ++ down(&priv->wx_sem); ++ if(priv->radion == 1) { ++ *(int *)extra = 1; ++ } else { ++ ++ *(int *)extra = 0; ++ } ++ up(&priv->wx_sem); ++ return 0; ++ ++} ++ ++static int r8180_wx_set_radion(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ int radion = *extra; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++// struct ieee80211_device *ieee = priv->ieee80211; ++ u8 btCR9346, btConfig3; ++ int i; ++ u16 u2bTFPC = 0; ++ u8 u1bTmp; ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ down(&priv->wx_sem); ++ printk("set radion = %d\n", radion); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(ieee->iw_mode == ieee->iw_ext_mode) { ++ printk("mesh mode:: could not set radi on/off = %d\n", radion); ++ up(&priv->wx_sem); ++ return 0; ++ } ++#endif ++ // Set EEM0 and EEM1 in 9346CR. ++ btCR9346 = read_nic_byte(dev, CR9346); ++ write_nic_byte(dev, CR9346, (btCR9346|0xC0) ); ++ // Set PARM_En in Config3. ++ btConfig3 = read_nic_byte(dev, CONFIG3); ++ write_nic_byte(dev, CONFIG3, (btConfig3|CONFIG3_PARM_En) ); ++ ++ if ( radion == 1) //radion off ++ { ++ printk("==================>RF on\n"); ++ write_nic_dword(dev, ANAPARAM, ANAPARM_ON); ++ write_nic_dword(dev, ANAPARAM2, ANAPARM2_ON); ++ write_nic_byte(dev, CONFIG4, (priv->RFProgType)); ++ ++ write_nic_byte(dev, 0x085, 0x24); // 061219, SD3 ED: for minicard CCK power leakage issue. ++ write_rtl8225(dev, 0x4, 0x9FF); ++ ++ u1bTmp = read_nic_byte(dev, 0x24E); ++ write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5|BIT6))) );// 070124 SD1 Alex: turn on CCK and OFDM. ++ priv->radion = 1; //radion on ++ } ++ else ++ { ++ printk("==================>RF off\n"); ++ for(i = 0; i < MAX_DOZE_WAITING_TIMES_87B; i++) ++ { // Make sure TX FIFO is empty befor turn off RFE pwoer. ++ u2bTFPC = read_nic_word(dev, TFPC); ++ if(u2bTFPC == 0) ++ { ++ break; ++ } ++ else ++ { ++ printk("%d times TFPC: %d != 0 before doze!\n", (i+1), u2bTFPC); ++ udelay(10); ++ } ++ } ++ if( i == MAX_DOZE_WAITING_TIMES_87B ) ++ { ++ printk("\n\n\n SetZebraRFPowerState8187B(): %d times TFPC: %d != 0 !!!\n\n\n",\ ++ MAX_DOZE_WAITING_TIMES_87B, u2bTFPC); ++ } ++ ++ u1bTmp = read_nic_byte(dev, 0x24E); ++ write_nic_byte(dev, 0x24E, (u1bTmp|BIT5|BIT6));// 070124 SD1 Alex: turn off CCK and OFDM. ++ ++ write_rtl8225(dev, 0x4,0x1FF); // Turn off RF first to prevent BB lock up, suggested by PJ, 2006.03.03. ++ write_nic_byte(dev, 0x085, 0x04); // 061219, SD3 ED: for minicard CCK power leakage issue. ++ ++ write_nic_byte(dev, CONFIG4, (priv->RFProgType|Config4_PowerOff)); ++ ++ write_nic_dword(dev, ANAPARAM, ANAPARM_OFF); ++ write_nic_dword(dev, ANAPARAM2, ANAPARM2_OFF); // 070301, SD1 William: to reduce RF off power consumption to 80 mA. ++ priv->radion = 0; //radion off ++ } ++ // Clear PARM_En in Config3. ++ btConfig3 &= ~(CONFIG3_PARM_En); ++ write_nic_byte(dev, CONFIG3, btConfig3); ++ // Clear EEM0 and EEM1 in 9346CR. ++ btCR9346 &= ~(0xC0); ++ write_nic_byte(dev, CR9346, btCR9346); ++ ++ up(&priv->wx_sem); ++ ++ return 0; ++} ++ ++static int r8180_wx_set_ratadpt (struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ int ratadapt = *extra; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ struct ieee80211_device *ieee = priv->ieee80211; ++ ++ if(priv->ieee80211->bHwRadioOff) ++ return 0; ++ ++ down(&priv->wx_sem); ++ printk("Set rate adaptive %s\n", (ratadapt==0)?"on":"off"); ++ if(ratadapt == 0) { ++ del_timer_sync(&priv->rateadapter_timer); ++ cancel_delayed_work(&priv->ieee80211->rate_adapter_wq); ++ priv->rateadapter_timer.function((unsigned long)dev); ++ } else { ++ del_timer_sync(&priv->rateadapter_timer); ++ cancel_delayed_work(&priv->ieee80211->rate_adapter_wq); ++ printk("force rate to %d\n", ratadapt); ++ ieee->rate = ratadapt; ++ } ++ up(&priv->wx_sem); ++ return 0; ++} ++ ++#ifdef ENABLE_TOSHIBA_CONFIG ++static int r8180_wx_get_tblidx(struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ //extern u8 chan_plan_index; ++ //printk("=========>%s(), %x\n", __FUNCTION__, priv->channel_plan); ++ down(&priv->wx_sem); ++ put_user(priv->channel_plan, (u8*)wrqu->data.pointer); ++ up(&priv->wx_sem); ++ return 0; ++ ++} ++ ++//This func will be called after probe auto ++static int r8180_wx_set_tbl (struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, char *extra) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u8 len = 0; ++ s8 err = -1; ++ extern CHANNEL_LIST Current_tbl; ++ down(&priv->wx_sem); ++ if (!wrqu->data.pointer) ++ { ++ printk("user data pointer is null\n"); ++ goto exit; ++ } ++ len = wrqu->data.length; ++ //printk("=========>%s(), len:%d\n", __FUNCTION__, len); ++ //memset(&Current_tbl, 0, sizeof(CHANNEL_LIST)); ++ if (copy_from_user((u8*)&Current_tbl, (void*)wrqu->data.pointer, len)) ++ { ++ printk("error copy from user\n"); ++ goto exit; ++ } ++ { ++ int i; ++ Current_tbl.Len = len; ++ //printk("%d\n", Current_tbl.Len); ++ ++ Dot11d_Init(priv->ieee80211); ++ priv->ieee80211->bGlobalDomain = false; ++ priv->ieee80211->bWorldWide13 = false; ++ ++ //lzm add 081205 ++ priv->ieee80211->MinPassiveChnlNum=12; ++ priv->ieee80211->IbssStartChnl= 10; ++ ++ for (i=0; ichannel_plan == COUNTRY_CODE_ETSI) ++ { ++ if(Current_tbl.Channel[i] <= 11) ++ { ++#ifdef ENABLE_DOT11D ++ GET_DOT11D_INFO(priv->ieee80211)->channel_map[Current_tbl.Channel[i]] = 1; ++#else ++ priv->ieee80211->channel_map[Current_tbl.Channel[i]] = 1; ++#endif ++ } ++ else if((Current_tbl.Channel[i] >= 11) && (Current_tbl.Channel[i] <= 13)) ++ { ++#ifdef ENABLE_DOT11D ++ GET_DOT11D_INFO(priv->ieee80211)->channel_map[Current_tbl.Channel[i]] = 2; ++#else ++ priv->ieee80211->channel_map[Current_tbl.Channel[i]] = 2; ++#endif ++ } ++ } ++ else ++ { ++ if(Current_tbl.Channel[i] <= 14) ++ { ++#ifdef ENABLE_DOT11D ++ GET_DOT11D_INFO(priv->ieee80211)->channel_map[Current_tbl.Channel[i]] = 1; ++#else ++ priv->ieee80211->channel_map[Current_tbl.Channel[i]] = 1; ++#endif ++ } ++ } ++ } ++#if 0 ++ printk("\n"); ++ for(i=1; iieee80211)->channel_map[i]); ++#else ++ printk("%2d ", priv->ieee80211->channel_map[i]); ++#endif ++ } ++ printk("\n"); ++ ++#endif ++ if(priv->ieee80211->proto_started) ++ {//we need to restart protocol now if it was start before channel map ++ ieee80211_softmac_stop_protocol(priv->ieee80211); ++ //mdelay(1); ++ ieee80211_softmac_start_protocol(priv->ieee80211); ++ } ++ } ++ err = 0; ++exit: ++ up(&priv->wx_sem); ++ return err; ++ ++ ++} ++ ++#endif ++ ++ ++static iw_handler r8180_wx_handlers[] = ++{ ++ NULL, /* SIOCSIWCOMMIT */ ++ r8180_wx_get_name, /* SIOCGIWNAME */ ++ dummy, /* SIOCSIWNWID */ ++ dummy, /* SIOCGIWNWID */ ++ r8180_wx_set_freq, /* SIOCSIWFREQ */ ++ r8180_wx_get_freq, /* SIOCGIWFREQ */ ++ r8180_wx_set_mode, /* SIOCSIWMODE */ ++ r8180_wx_get_mode, /* SIOCGIWMODE */ ++ r8180_wx_set_sens, /* SIOCSIWSENS */ ++ r8180_wx_get_sens, /* SIOCGIWSENS */ ++ NULL, /* SIOCSIWRANGE */ ++ rtl8180_wx_get_range, /* SIOCGIWRANGE */ ++ NULL, /* SIOCSIWPRIV */ ++ NULL, /* SIOCGIWPRIV */ ++ NULL, /* SIOCSIWSTATS */ ++ NULL, /* SIOCGIWSTATS */ ++ dummy, /* SIOCSIWSPY */ ++ dummy, /* SIOCGIWSPY */ ++ NULL, /* SIOCGIWTHRSPY */ ++ NULL, /* SIOCWIWTHRSPY */ ++ r8180_wx_set_wap, /* SIOCSIWAP */ ++ r8180_wx_get_wap, /* SIOCGIWAP */ ++ r8180_wx_set_mlme, //NULL, /* SIOCSIWMLME*/ /* -- hole -- */ ++ dummy, /* SIOCGIWAPLIST -- depricated */ ++ r8180_wx_set_scan, /* SIOCSIWSCAN */ ++ r8180_wx_get_scan, /* SIOCGIWSCAN */ ++ r8180_wx_set_essid, /* SIOCSIWESSID */ ++ r8180_wx_get_essid, /* SIOCGIWESSID */ ++ dummy, /* SIOCSIWNICKN */ ++ dummy, /* SIOCGIWNICKN */ ++ NULL, /* -- hole -- */ ++ NULL, /* -- hole -- */ ++ r8180_wx_set_rate, /* SIOCSIWRATE */ ++ r8180_wx_get_rate, /* SIOCGIWRATE */ ++ dummy, /* SIOCSIWRTS */ ++ dummy, /* SIOCGIWRTS */ ++ r8180_wx_set_frag, /* SIOCSIWFRAG */ ++ r8180_wx_get_frag, /* SIOCGIWFRAG */ ++ dummy, /* SIOCSIWTXPOW */ ++ dummy, /* SIOCGIWTXPOW */ ++ r8180_wx_set_retry, /* SIOCSIWRETRY */ ++ r8180_wx_get_retry, /* SIOCGIWRETRY */ ++ r8180_wx_set_enc, /* SIOCSIWENCODE */ ++ r8180_wx_get_enc, /* SIOCGIWENCODE */ ++ dummy, /* SIOCSIWPOWER */ ++ dummy, /* SIOCGIWPOWER */ ++ NULL, /*---hole---*/ ++ NULL, /*---hole---*/ ++ r8180_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */ ++ NULL, /* SIOCSIWGENIE */ ++ r8180_wx_set_auth,//NULL, /* SIOCSIWAUTH */ ++ NULL,//r8180_wx_get_auth,//NULL, /* SIOCSIWAUTH */ ++ r8180_wx_set_enc_ext, /* SIOCSIWENCODEEXT */ ++ NULL,//r8180_wx_get_enc_ext,//NULL, /* SIOCSIWENCODEEXT */ ++ NULL, /* SIOCSIWPMKSA */ ++ NULL, /*---hole---*/ ++}; ++ ++ ++static const struct iw_priv_args r8180_private_args[] = { ++ { ++ SIOCIWFIRSTPRIV + 0x0, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc" ++ }, ++ ++ { ++ SIOCIWFIRSTPRIV + 0x1, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan" ++ ++ }, ++ { ++ SIOCIWFIRSTPRIV + 0x2, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx" ++ }, ++#ifdef JOHN_IOCTL ++ { ++ SIOCIWFIRSTPRIV + 0x3, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readRF" ++ } ++ , ++ { ++ SIOCIWFIRSTPRIV + 0x4, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeRF" ++ } ++ , ++ { ++ SIOCIWFIRSTPRIV + 0x5, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readBB" ++ } ++ , ++ { ++ SIOCIWFIRSTPRIV + 0x6, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeBB" ++ } ++ , ++ { ++ SIOCIWFIRSTPRIV + 0x7, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readnicb" ++ } ++ , ++ { ++ SIOCIWFIRSTPRIV + 0x8, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writenicb" ++ } ++ , ++ { ++ SIOCIWFIRSTPRIV + 0x9, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo" ++ }, ++#endif ++ { ++ SIOCIWFIRSTPRIV + 0xA, ++ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED |1, "getradion" ++ }, ++ { ++ SIOCIWFIRSTPRIV + 0xB, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setradion" ++ }, ++ { ++ SIOCIWFIRSTPRIV + 0xC, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ratadpt" ++ }, ++#ifdef ENABLE_TOSHIBA_CONFIG ++ { ++ SIOCIWFIRSTPRIV + 0xD, ++ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettblidx" ++ }, ++ { ++ SIOCIWFIRSTPRIV + 0xE, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,0, "settblidx" ++ }, ++ ++#endif ++ ++}; ++ ++/* ++ * Private ioctl interface information ++ ++struct iw_priv_args ++{ ++// __u32 cmd; ++// __u16 set_args; ++// __u16 get_args; ++// char name[IFNAMSIZ]; ++//}; ++*/ ++//If get cmd's number is big,there may cause some problemes. ++//So modified by Lawrence,071120 ++ ++static iw_handler r8180_private_handler[] = { ++// r8180_wx_set_monitor, /* SIOCIWFIRSTPRIV */ ++ r8180_wx_set_crcmon, /*SIOCIWSECONDPRIV*/ ++// r8180_wx_set_forceassociate, ++// r8180_wx_set_beaconinterval, ++// r8180_wx_set_monitor_type, ++ r8180_wx_set_scan_type, ++ r8180_wx_set_rawtx, ++ ++#if 0 ++#ifdef _RTL8187_EXT_PATCH_ ++ r8180_wx_get_meshinfo, ++ r8180_wx_enable_mesh, ++ r8180_wx_disable_mesh, ++ r8180_wx_set_channel, ++ r8180_wx_set_meshID, ++ ++// r8180_wx_add_mac_allow, ++// r8180_wx_get_mac_allow, ++// r8180_wx_del_mac_allow, ++ r8180_wx_add_mac_deny, ++ r8180_wx_get_mac_deny, ++ r8180_wx_del_mac_deny, ++ r8180_wx_get_mesh_list, ++ r8180_wx_mesh_scan, ++ r8180_wx_join_mesh, ++#endif ++#endif ++ ++#ifdef JOHN_IOCTL ++ r8180_wx_read_regs, ++ r8180_wx_write_regs, ++ r8180_wx_read_bb, ++ r8180_wx_write_bb, ++ r8180_wx_read_nicb, ++ r8180_wx_write_nicb, ++ r8180_wx_get_ap_status, ++#endif ++ r8180_wx_get_radion, ++ r8180_wx_set_radion, ++ r8180_wx_set_ratadpt, ++#ifdef ENABLE_TOSHIBA_CONFIG ++ r8180_wx_get_tblidx, ++ r8180_wx_set_tbl, ++#endif ++}; ++ ++#if WIRELESS_EXT >= 17 ++//WB modefied to show signal to GUI on 18-01-2008 ++static struct iw_statistics *r8180_get_wireless_stats(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ struct ieee80211_device* ieee = priv->ieee80211; ++ struct iw_statistics* wstats = &priv->wstats; ++// struct ieee80211_network* target = NULL; ++ int tmp_level = 0; ++ int tmp_qual = 0; ++ int tmp_noise = 0; ++// unsigned long flag; ++ ++ if (ieee->state < IEEE80211_LINKED) ++ { ++ wstats->qual.qual = 0; ++ wstats->qual.level = 0; ++ wstats->qual.noise = 0; ++ wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; ++ return wstats; ++ } ++#if 0 ++ spin_lock_irqsave(&ieee->lock, flag); ++ list_for_each_entry(target, &ieee->network_list, list) ++ { ++ if (is_same_network(target, &ieee->current_network)) ++ { ++ printk("it's same network:%s\n", target->ssid); ++#if 0 ++ if (!tmp_level) ++ { ++ tmp_level = target->stats.signalstrength; ++ tmp_qual = target->stats.signal; ++ } ++ else ++ { ++ ++ tmp_level = (15*tmp_level + target->stats.signalstrength)/16; ++ tmp_qual = (15*tmp_qual + target->stats.signal)/16; ++ } ++#else ++ tmp_level = target->stats.signal; ++ tmp_qual = target->stats.signalstrength; ++ tmp_noise = target->stats.noise; ++ printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise); ++#endif ++ break; ++ } ++ } ++ spin_unlock_irqrestore(&ieee->lock, flag); ++#endif ++ tmp_level = (&ieee->current_network)->stats.signal; ++ tmp_qual = (&ieee->current_network)->stats.signalstrength; ++ tmp_noise = (&ieee->current_network)->stats.noise; ++ //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise); ++ ++ wstats->qual.level = tmp_level; ++ wstats->qual.qual = tmp_qual; ++ wstats->qual.noise = tmp_noise; ++ wstats->qual.updated = IW_QUAL_ALL_UPDATED| IW_QUAL_DBM; ++ return wstats; ++} ++#endif ++ ++ ++struct iw_handler_def r8180_wx_handlers_def={ ++ .standard = r8180_wx_handlers, ++ .num_standard = sizeof(r8180_wx_handlers) / sizeof(iw_handler), ++ .private = r8180_private_handler, ++ .num_private = sizeof(r8180_private_handler) / sizeof(iw_handler), ++ .num_private_args = sizeof(r8180_private_args) / sizeof(struct iw_priv_args), ++#if WIRELESS_EXT >= 17 ++ .get_wireless_stats = r8180_get_wireless_stats, ++#endif ++ .private_args = (struct iw_priv_args *)r8180_private_args, ++}; ++#ifdef _RTL8187_EXT_PATCH_ ++EXPORT_SYMBOL(r8180_wx_set_channel); ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_wx.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_wx.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8180_wx.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8180_wx.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,21 @@ ++/* ++ This is part of rtl8180 OpenSource driver - v 0.3 ++ Copyright (C) Andrea Merello 2004 ++ Released under the terms of GPL (General Public Licence) ++ ++ Parts of this driver are based on the GPL part of the official realtek driver ++ Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon ++ Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver ++ ++ We want to tanks the Authors of such projects and the Ndiswrapper project Authors. ++*/ ++ ++/* this file (will) contains wireless extension handlers*/ ++ ++#ifndef R8180_WX_H ++#define R8180_WX_H ++#include ++#include "ieee80211/ieee80211.h" ++extern struct iw_handler_def r8180_wx_handlers_def; ++ ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8187_core.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8187_core.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8187_core.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8187_core.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,7194 @@ ++/* ++ This is part of rtl8187 OpenSource driver - v 0.1 ++ Copyright (C) Andrea Merello 2005 ++ Released under the terms of GPL (General Public License) ++ ++ ++ Parts of this driver are based on the rtl8180 driver skeleton ++ from Patric Schenke & Andres Salomon. ++ ++ Parts of this driver are based on the Intel Pro Wireless 2*00 GPL drivers. ++ ++ some ideas might be derived from David Young rtl8180 netbsd driver. ++ ++ Parts of the usb code are from the r8150.c driver in linux kernel ++ ++ Some ideas borrowed from the 8139too.c driver included in linux kernel. ++ ++ We (I?) want to thanks the Authors of those projecs and also the ++ Ndiswrapper's project Authors. ++ ++ A special big thanks goes also to Realtek corp. for their help in my ++ attempt to add RTL8187 and RTL8225 support, and to David Young also. ++ ++ - Please note that this file is a modified version from rtl8180-sa2400 ++ drv. So some other people have contributed to this project, and they are ++ thanked in the rtl8180-sa2400 CHANGELOG. ++*/ ++ ++#undef LOOP_TEST ++#undef DUMP_RX ++#undef DUMP_TX ++#undef DEBUG_TX_DESC2 ++#undef RX_DONT_PASS_UL ++#undef DEBUG_EPROM ++#undef DEBUG_RX_VERBOSE ++#undef DUMMY_RX ++#undef DEBUG_ZERO_RX ++#undef DEBUG_RX_SKB ++#undef DEBUG_TX_FRAG ++#undef DEBUG_RX_FRAG ++#undef DEBUG_TX_FILLDESC ++#undef DEBUG_TX ++#undef DEBUG_IRQ ++#undef DEBUG_RX ++#undef DEBUG_RXALLOC ++#undef DEBUG_REGISTERS ++#undef DEBUG_RING ++#undef DEBUG_IRQ_TASKLET ++#undef DEBUG_TX_ALLOC ++#undef DEBUG_TX_DESC ++#undef CONFIG_SOFT_BEACON ++#undef DEBUG_RW_REGISTER ++ ++#define CONFIG_RTL8180_IO_MAP ++//#define CONFIG_SOFT_BEACON ++//#define DEBUG_RW_REGISTER ++ ++#include ++ ++#include "r8180_hw.h" ++#include "r8187.h" ++#include "r8180_rtl8225.h" /* RTL8225 Radio frontend */ ++#include "r8180_93cx6.h" /* Card EEPROM */ ++#include "r8180_wx.h" ++#include "r8180_dm.h" ++ ++#include ++// FIXME: check if 2.6.7 is ok ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)) ++#define usb_kill_urb usb_unlink_urb ++#endif ++ ++#ifdef CONFIG_RTL8180_PM ++#include "r8180_pm.h" ++#endif ++ ++#ifdef ENABLE_DOT11D ++#include "dot11d.h" ++#endif ++ ++#ifndef USB_VENDOR_ID_REALTEK ++#define USB_VENDOR_ID_REALTEK 0x0bda ++#endif ++#ifndef USB_VENDOR_ID_NETGEAR ++#define USB_VENDOR_ID_NETGEAR 0x0846 ++#endif ++ ++#define TXISR_SELECT(priority) ((priority == MANAGE_PRIORITY)?rtl8187_managetx_isr:\ ++ (priority == BEACON_PRIORITY)?rtl8187_beacontx_isr: \ ++ (priority == VO_PRIORITY)?rtl8187_votx_isr: \ ++ (priority == VI_PRIORITY)?rtl8187_vitx_isr:\ ++ (priority == BE_PRIORITY)?rtl8187_betx_isr:rtl8187_bktx_isr) ++ ++static struct usb_device_id rtl8187_usb_id_tbl[] = { ++ {USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8187)}, ++ {USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8189)}, ++// {USB_DEVICE_VER(USB_VENDOR_ID_REALTEK, 0x8187,0x0200,0x0200)}, ++ {USB_DEVICE(USB_VENDOR_ID_NETGEAR, 0x6100)}, ++ {USB_DEVICE(USB_VENDOR_ID_NETGEAR, 0x6a00)}, ++ {USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8197)}, ++ {USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8198)}, ++ {} ++}; ++ ++static char* ifname = "wlan%d"; ++#if 0 ++static int hwseqnum = 0; ++static int hwwep = 0; ++#endif ++static int channels = 0x3fff; ++//static int channels = 0x7ff;// change by thomas, use 1 - 11 channel 0907-2007 ++#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 ) ++//by amy for rate adaptive ++#define DEFAULT_RATE_ADAPTIVE_TIMER_PERIOD 300 ++//by amy for rate adaptive ++//by amy for ps ++#define IEEE80211_WATCH_DOG_TIME 2000 ++//by amy for ps ++MODULE_LICENSE("GPL"); ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++MODULE_VERSION("V 1.1"); ++#endif ++MODULE_DEVICE_TABLE(usb, rtl8187_usb_id_tbl); ++MODULE_AUTHOR("Realsil Wlan"); ++MODULE_DESCRIPTION("Linux driver for Realtek RTL8187 WiFi cards"); ++ ++#if 0 ++MODULE_PARM(ifname,"s"); ++MODULE_PARM_DESC(devname," Net interface name, wlan%d=default"); ++ ++MODULE_PARM(hwseqnum,"i"); ++MODULE_PARM_DESC(hwseqnum," Try to use hardware 802.11 header sequence numbers. Zero=default"); ++ ++MODULE_PARM(hwwep,"i"); ++MODULE_PARM_DESC(hwwep," Try to use hardware WEP support. Still broken and not available on all cards"); ++ ++MODULE_PARM(channels,"i"); ++MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI"); ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9) ++module_param(ifname, charp, S_IRUGO|S_IWUSR ); ++//module_param(hwseqnum,int, S_IRUGO|S_IWUSR); ++//module_param(hwwep,int, S_IRUGO|S_IWUSR); ++module_param(channels,int, S_IRUGO|S_IWUSR); ++#else ++MODULE_PARM(ifname, "s"); ++//MODULE_PARM(hwseqnum,"i"); ++//MODULE_PARM(hwwep,"i"); ++MODULE_PARM(channels,"i"); ++#endif ++ ++MODULE_PARM_DESC(devname," Net interface name, wlan%d=default"); ++//MODULE_PARM_DESC(hwseqnum," Try to use hardware 802.11 header sequence numbers. Zero=default"); ++//MODULE_PARM_DESC(hwwep," Try to use hardware WEP support. Still broken and not available on all cards"); ++MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI"); ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++static int __devinit rtl8187_usb_probe(struct usb_interface *intf, ++ const struct usb_device_id *id); ++static void __devexit rtl8187_usb_disconnect(struct usb_interface *intf); ++#else ++static void *__devinit rtl8187_usb_probe(struct usb_device *udev,unsigned int ifnum, ++ const struct usb_device_id *id); ++static void __devexit rtl8187_usb_disconnect(struct usb_device *udev, void *ptr); ++#endif ++ ++ ++static struct usb_driver rtl8187_usb_driver = { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) ++ .owner = THIS_MODULE, ++#endif ++ .name = RTL8187_MODULE_NAME, /* Driver name */ ++ .id_table = rtl8187_usb_id_tbl, /* PCI_ID table */ ++ .probe = rtl8187_usb_probe, /* probe fn */ ++ .disconnect = rtl8187_usb_disconnect, /* remove fn */ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0) ++#ifdef CONFIG_RTL8180_PM ++ .suspend = rtl8187_suspend, /* PM suspend fn */ ++ .resume = rtl8187_resume, /* PM resume fn */ ++#else ++ .suspend = NULL, /* PM suspend fn */ ++ .resume = NULL, /* PM resume fn */ ++#endif ++#endif ++}; ++ ++#ifdef JOHN_HWSEC ++void CAM_mark_invalid(struct net_device *dev, u8 ucIndex) ++{ ++ u32 ulContent=0; ++ u32 ulCommand=0; ++ u32 ulEncAlgo=CAM_AES; ++ ++ // keyid must be set in config field ++ ulContent |= (ucIndex&3) | ((u16)(ulEncAlgo)<<2); ++ ++ ulContent |= BIT15; ++ // polling bit, and No Write enable, and address ++ ulCommand= CAM_CONTENT_COUNT*ucIndex; ++ ulCommand= ulCommand | BIT31|BIT16; ++ // write content 0 is equall to mark invalid ++ ++ write_nic_dword(dev, WCAMI, ulContent); //delay_ms(40); ++ //RT_TRACE(COMP_SEC, DBG_LOUD, ("CAM_mark_invalid(): WRITE A4: %x \n",ulContent)); ++ write_nic_dword(dev, RWCAM, ulCommand); //delay_ms(40); ++ //RT_TRACE(COMP_SEC, DBG_LOUD, ("CAM_mark_invalid(): WRITE A0: %x \n",ulCommand)); ++} ++ ++void CAM_empty_entry(struct net_device *dev, u8 ucIndex) ++{ ++ u32 ulCommand=0; ++ u32 ulContent=0; ++ u8 i; ++ u32 ulEncAlgo=CAM_AES; ++ ++ for(i=0;i<6;i++) ++ { ++ ++ // filled id in CAM config 2 byte ++ if( i == 0) ++ { ++ ulContent |=(ucIndex & 0x03) | (ulEncAlgo<<2); ++ ulContent |= BIT15; ++ ++ } ++ else ++ { ++ ulContent = 0; ++ } ++ // polling bit, and No Write enable, and address ++ ulCommand= CAM_CONTENT_COUNT*ucIndex+i; ++ ulCommand= ulCommand | BIT31|BIT16; ++ // write content 0 is equall to mark invalid ++ write_nic_dword(dev, WCAMI, ulContent); //delay_ms(40); ++ //RT_TRACE(COMP_SEC, DBG_LOUD, ("CAM_empty_entry(): WRITE A4: %x \n",ulContent)); ++ write_nic_dword(dev, RWCAM, ulCommand); //delay_ms(40); ++ //RT_TRACE(COMP_SEC, DBG_LOUD, ("CAM_empty_entry(): WRITE A0: %x \n",ulCommand)); ++ } ++} ++ ++void CamResetAllEntry(struct net_device *dev) ++{ ++ u8 ucIndex; ++ ++ //2004/02/11 In static WEP, OID_ADD_KEY or OID_ADD_WEP are set before STA associate to AP. ++ // However, ResetKey is called on OID_802_11_INFRASTRUCTURE_MODE and MlmeAssociateRequest ++ // In this condition, Cam can not be reset because upper layer will not set this static key again. ++ //if(Adapter->EncAlgorithm == WEP_Encryption) ++ // return; ++ //debug ++ //DbgPrint("========================================\n"); ++ //DbgPrint(" Call ResetAllEntry \n"); ++ //DbgPrint("========================================\n\n"); ++ ++ for(ucIndex=0;ucIndexwrite_read_register_index % 200) ; ++ ++ priv->write_read_registers[reg_index].address = 0; ++ priv->write_read_registers[reg_index].content = 0; ++ priv->write_read_registers[reg_index].flag = 0; ++ ++ priv->write_read_registers[reg_index].address = addr; ++ priv->write_read_registers[reg_index].content = cont; ++ priv->write_read_registers[reg_index].flag = flag; ++ ++ priv->write_read_register_index = (priv->write_read_register_index + 1) % 200; ++} ++ ++bool print_once = 0; ++ ++void print_rw_registers(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ int reg_index = 0; ++ int watchdog = 0; ++ if(print_once == false) ++ { ++ print_once = true; ++ for(reg_index = ((priv->write_read_register_index + 1) % 200); watchdog <= 199; reg_index++) ++ { ++ watchdog++; ++ printk("====>reg_addr:0x%x, reg_cont:0x%x, read_or_write:0x%d\n", ++ priv->write_read_registers[reg_index].address, ++ priv->write_read_registers[reg_index].content, ++ priv->write_read_registers[reg_index].flag); ++ } ++ } ++} ++//lzm add for write time out test ++#endif ++ ++#ifdef CPU_64BIT ++void write_nic_byte_E(struct net_device *dev, int indx, u8 data) ++{ ++ int status; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), ++ RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, ++ indx|0xfe00, 0, &data, 1, HZ / 2); ++ ++//lzm add for write time out test ++#ifdef DEBUG_RW_REGISTER ++ add_into_rw_registers(dev, indx, data, 2); ++#endif ++ ++ if (status < 0) ++ { ++ printk("write_nic_byte_E TimeOut!addr:%x, status:%x\n", indx, status); ++#ifdef DEBUG_RW_REGISTER ++ print_rw_registers(dev); ++#endif ++ } ++} ++ ++u8 read_nic_byte_E(struct net_device *dev, int indx) ++{ ++ int status; ++ u8 data, *buf; ++ dma_addr_t dma_handle; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ buf = dma_pool_alloc(priv->usb_pool, GFP_ATOMIC, &dma_handle); ++ if (!buf) { ++ printk("read_nic_byte_E out of memory\n"); ++ return -ENOMEM; ++ } ++ status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ++ RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, ++ indx|0xfe00, 0, buf, 1, HZ / 2); ++//lzm add for write time out test ++#ifdef DEBUG_RW_REGISTER ++ add_into_rw_registers(dev, indx, buf[0], 1); ++#endif ++ ++ if (status < 0) ++ { ++ printk("read_nic_byte_E TimeOut!addr:%x, status:%x\n",indx, status); ++#ifdef DEBUG_RW_REGISTER ++ print_rw_registers(dev); ++#endif ++ } ++ ++ data = buf[0]; ++ dma_pool_free(priv->usb_pool, buf, dma_handle); ++ return data; ++} ++ ++void write_nic_byte(struct net_device *dev, int indx, u8 data) ++{ ++ int status; ++ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), ++ RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, ++ (indx&0xff)|0xff00, (indx>>8)&0x03, &data, 1, HZ / 2); ++ ++//lzm add for write time out test ++#ifdef DEBUG_RW_REGISTER ++ add_into_rw_registers(dev, indx, data, 2); ++#endif ++ if (status < 0) ++ { ++ printk("write_nic_byte TimeOut!addr:%x, status:%x\n",indx, status); ++#ifdef DEBUG_RW_REGISTER ++ print_rw_registers(dev); ++#endif ++ } ++ ++ ++} ++ ++void write_nic_word(struct net_device *dev, int indx, u16 data) ++{ ++ ++ int status; ++ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), ++ RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, ++ (indx&0xff)|0xff00, (indx>>8)&0x03, &data, 2, HZ / 2); ++ ++//lzm add for write time out test ++#ifdef DEBUG_RW_REGISTER ++ add_into_rw_registers(dev, indx, data, 2); ++ ++ if(priv->write_read_register_index == 199) ++ { ++ //print_rw_registers(dev); ++ } ++#endif ++ if (status < 0) ++ { ++ printk("write_nic_word TimeOut!addr:%x, status:%x\n",indx, status); ++#ifdef DEBUG_RW_REGISTER ++ print_rw_registers(dev); ++#endif ++ } ++ ++} ++ ++void write_nic_dword(struct net_device *dev, int indx, u32 data) ++{ ++ ++ int status; ++ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), ++ RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, ++ (indx&0xff)|0xff00, (indx>>8)&0x03, &data, 4, HZ / 2); ++//lzm add for write time out test ++#ifdef DEBUG_RW_REGISTER ++ add_into_rw_registers(dev, indx, data, 2); ++#endif ++ ++ ++ if (status < 0) ++ { ++ printk("write_nic_dword TimeOut!addr:%x, status:%x\n",indx, status); ++#ifdef DEBUG_RW_REGISTER ++ print_rw_registers(dev); ++#endif ++ } ++ ++} ++ ++ u8 read_nic_byte(struct net_device *dev, int indx) ++{ ++ u8 data, *buf; ++ int status; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ dma_addr_t dma_handle; ++ ++ buf = dma_pool_alloc(priv->usb_pool, GFP_ATOMIC, &dma_handle); ++ if (!buf) { ++ printk("read_nic_byte: out of memory\n"); ++ return -ENOMEM; ++ } ++ status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ++ RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, ++ (indx&0xff)|0xff00, (indx>>8)&0x03, buf, 1, HZ / 2); ++//lzm add for write time out test ++#ifdef DEBUG_RW_REGISTER ++ add_into_rw_registers(dev, indx, buf[0], 1); ++#endif ++ ++ if (status < 0) ++ { ++ printk("read_nic_byte TimeOut!addr:%x, status:%x\n",indx, status); ++#ifdef DEBUG_RW_REGISTER ++ print_rw_registers(dev); ++#endif ++ } ++ ++ data = buf[0]; ++ dma_pool_free(priv->usb_pool, buf, dma_handle); ++ return data; ++} ++ ++u16 read_nic_word(struct net_device *dev, int indx) ++{ ++ u16 data, *buf; ++ int status; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ dma_addr_t dma_handle; ++ ++ buf = dma_pool_alloc(priv->usb_pool, GFP_ATOMIC, &dma_handle); ++ if (!buf) { ++ printk("read_nic_word: out of memory\n"); ++ return -ENOMEM; ++ } ++ status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ++ RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, ++ (indx&0xff)|0xff00, (indx>>8)&0x03, buf, 2, HZ / 2); ++//lzm add for write time out test ++#ifdef DEBUG_RW_REGISTER ++ add_into_rw_registers(dev, indx, buf[0], 1); ++#endif ++ ++ if (status < 0) ++ { ++ printk("read_nic_word TimeOut!addr:%x, status:%x\n",indx, status); ++#ifdef DEBUG_RW_REGISTER ++ print_rw_registers(dev); ++#endif ++ } ++ ++ ++ data = buf[0]; ++ dma_pool_free(priv->usb_pool, buf, dma_handle); ++ return data; ++} ++ ++u32 read_nic_dword(struct net_device *dev, int indx) ++{ ++ u32 data, *buf; ++ int status; ++ dma_addr_t dma_handle; ++// int result; ++ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ buf = dma_pool_alloc(priv->usb_pool, GFP_ATOMIC, &dma_handle); ++ if (!buf){ ++ printk("read_nic_dword: out of memory\n"); ++ return -ENOMEM; ++ } ++ status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ++ RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, ++ (indx&0xff)|0xff00, (indx>>8)&0x03, buf, 4, HZ / 2); ++//lzm add for write time out test ++#ifdef DEBUG_RW_REGISTER ++ add_into_rw_registers(dev, indx, buf[0], 1); ++#endif ++ ++ if (status < 0) ++ { ++ printk("read_nic_dword TimeOut!addr:%x, status:%x\n",indx, status); ++#ifdef DEBUG_RW_REGISTER ++ print_rw_registers(dev); ++#endif ++ } ++ ++ ++ ++ data = buf[0]; ++ dma_pool_free(priv->usb_pool, buf, dma_handle); ++ return data; ++} ++#else ++void write_nic_byte_E(struct net_device *dev, int indx, u8 data) ++{ ++ int status; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), ++ RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, ++ indx|0xfe00, 0, &data, 1, HZ / 2); ++ ++ if (status < 0) ++ { ++ printk("write_nic_byte_E TimeOut!addr:0x%x,val:0x%x, status:%x\n", indx,data,status); ++ } ++} ++ ++u8 read_nic_byte_E(struct net_device *dev, int indx) ++{ ++ int status; ++ u8 data = 0; ++ u8 buf[64]; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ++ RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, ++ indx|0xfe00, 0, buf, 1, HZ / 2); ++ ++ if (status < 0) ++ { ++ printk("read_nic_byte_E TimeOut!addr:0x%x, status:%x\n", indx, status); ++ } ++ ++ data = *(u8*)buf; ++ return data; ++} ++ ++void write_nic_byte(struct net_device *dev, int indx, u8 data) ++{ ++ int status; ++ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), ++ RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, ++ (indx&0xff)|0xff00, (indx>>8)&0x03, &data, 1, HZ / 2); ++ ++ if (status < 0) ++ { ++ printk("write_nic_byte TimeOut!addr:0x%x,val:0x%x, status:%x\n", indx,data, status); ++ } ++ ++ ++} ++ ++void write_nic_word(struct net_device *dev, int indx, u16 data) ++{ ++ ++ int status; ++ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), ++ RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, ++ (indx&0xff)|0xff00, (indx>>8)&0x03, &data, 2, HZ / 2); ++ ++ if (status < 0) ++ { ++ printk("write_nic_word TimeOut!addr:0x%x,val:0x%x, status:%x\n", indx,data, status); ++ } ++ ++} ++ ++void write_nic_dword(struct net_device *dev, int indx, u32 data) ++{ ++ ++ int status; ++ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), ++ RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, ++ (indx&0xff)|0xff00, (indx>>8)&0x03, &data, 4, HZ / 2); ++ ++ ++ if (status < 0) ++ { ++ printk("write_nic_dword TimeOut!addr:0x%x,val:0x%x, status:%x\n", indx,data, status); ++ } ++ ++} ++ ++u8 read_nic_byte(struct net_device *dev, int indx) ++{ ++ u8 data = 0; ++ u8 buf[64]; ++ int status; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ++ RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, ++ (indx&0xff)|0xff00, (indx>>8)&0x03, buf, 1, HZ / 2); ++ ++ if (status < 0) ++ { ++ printk("read_nic_byte TimeOut!addr:0x%x,status:%x\n", indx,status); ++ } ++ ++ ++ data = *(u8*)buf; ++ return data; ++} ++ ++u16 read_nic_word(struct net_device *dev, int indx) ++{ ++ u16 data = 0; ++ u8 buf[64]; ++ int status; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ++ RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, ++ (indx&0xff)|0xff00, (indx>>8)&0x03, buf, 2, HZ / 2); ++ ++ if (status < 0) ++ { ++ printk("read_nic_word TimeOut!addr:0x%x,status:%x\n", indx,status); ++ } ++ ++ data = *(u16*)buf; ++ return data; ++} ++ ++u32 read_nic_dword(struct net_device *dev, int indx) ++{ ++ u32 data = 0; ++ u8 buf[64]; ++ int status; ++ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct usb_device *udev = priv->udev; ++ ++ status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ++ RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, ++ (indx&0xff)|0xff00, (indx>>8)&0x03, buf, 4, HZ / 2); ++ ++ if (status < 0) ++ { ++ printk("read_nic_dword TimeOut!addr:0x%x,status:%x\n", indx, status); ++ } ++ ++ ++ data = *(u32*)buf; ++ return data; ++} ++#endif ++ ++ ++u8 read_phy_cck(struct net_device *dev, u8 adr); ++u8 read_phy_ofdm(struct net_device *dev, u8 adr); ++/* this might still called in what was the PHY rtl8185/rtl8187 common code ++ * plans are to possibilty turn it again in one common code... ++ */ ++inline void force_pci_posting(struct net_device *dev) ++{ ++} ++ ++ ++static struct net_device_stats *rtl8180_stats(struct net_device *dev); ++void rtl8180_commit(struct net_device *dev); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void rtl8180_restart(struct work_struct *work); ++#else ++void rtl8180_restart(struct net_device *dev); ++#endif ++/**************************************************************************** ++ -----------------------------PROCFS STUFF------------------------- ++*****************************************************************************/ ++ ++static struct proc_dir_entry *rtl8180_proc = NULL; ++static int proc_get_stats_ap(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) ++{ ++ struct net_device *dev = data; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct ieee80211_device *ieee = priv->ieee80211; ++ struct ieee80211_network *target; ++ ++ int len = 0; ++ ++ list_for_each_entry(target, &ieee->network_list, list) { ++ ++ len += snprintf(page + len, count - len, ++ "%s ", target->ssid); ++ len += snprintf(page + len, count - len, ++ "%ld ", (jiffies-target->last_scanned)/HZ); ++ ++ ++ ++ if(target->wpa_ie_len>0 || target->rsn_ie_len>0){ ++ len += snprintf(page + len, count - len, ++ "WPA\n"); ++ } ++ else{ ++ len += snprintf(page + len, count - len, ++ "non_WPA\n"); ++ } ++ ++ } ++ ++ *eof = 1; ++ return len; ++} ++ ++static int proc_get_registers(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) ++{ ++ struct net_device *dev = data; ++ ++ int len = 0; ++ int i,n; ++ ++ int max=0xff; ++ ++ /* This dump the current register page */ ++len += snprintf(page + len, count - len, ++ "\n####################page 0##################\n "); ++ ++ for(n=0;n<=max;) ++ { ++ //printk( "\nD: %2x> ", n); ++ len += snprintf(page + len, count - len, ++ "\nD: %2x > ",n); ++ ++ for(i=0;i<16 && n<=max;i++,n++) ++ len += snprintf(page + len, count - len, ++ "%2x ",read_nic_byte(dev,n)); ++ ++ // printk("%2x ",read_nic_byte(dev,n)); ++ } ++ len += snprintf(page + len, count - len,"\n"); ++len += snprintf(page + len, count - len, ++ "\n####################page 1##################\n "); ++ for(n=0;n<=max;) ++ { ++ //printk( "\nD: %2x> ", n); ++ len += snprintf(page + len, count - len, ++ "\nD: %2x > ",n); ++ ++ for(i=0;i<16 && n<=max;i++,n++) ++ len += snprintf(page + len, count - len, ++ "%2x ",read_nic_byte(dev,0x100|n)); ++ ++ // printk("%2x ",read_nic_byte(dev,n)); ++ } ++len += snprintf(page + len, count - len, ++ "\n####################page 2##################\n "); ++ for(n=0;n<=max;) ++ { ++ //printk( "\nD: %2x> ", n); ++ len += snprintf(page + len, count - len, ++ "\nD: %2x > ",n); ++ ++ for(i=0;i<16 && n<=max;i++,n++) ++ len += snprintf(page + len, count - len, ++ "%2x ",read_nic_byte(dev,0x200|n)); ++ ++ // printk("%2x ",read_nic_byte(dev,n)); ++ } ++ ++ ++ ++ *eof = 1; ++ return len; ++ ++} ++ ++ ++static int proc_get_cck_reg(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) ++{ ++ struct net_device *dev = data; ++ ++ int len = 0; ++ int i,n; ++ ++ int max = 0x5F; ++ ++ /* This dump the current register page */ ++ for(n=0;n<=max;) ++ { ++ //printk( "\nD: %2x> ", n); ++ len += snprintf(page + len, count - len, ++ "\nD: %2x > ",n); ++ ++ for(i=0;i<16 && n<=max;i++,n++) ++ len += snprintf(page + len, count - len, ++ "%2x ",read_phy_cck(dev,n)); ++ ++ // printk("%2x ",read_nic_byte(dev,n)); ++ } ++ len += snprintf(page + len, count - len,"\n"); ++ ++ ++ *eof = 1; ++ return len; ++ ++} ++ ++ ++static int proc_get_ofdm_reg(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) ++{ ++ struct net_device *dev = data; ++ ++ int len = 0; ++ int i,n; ++ ++ //int max=0xff; ++ int max = 0x40; ++ ++ /* This dump the current register page */ ++ for(n=0;n<=max;) ++ { ++ //printk( "\nD: %2x> ", n); ++ len += snprintf(page + len, count - len, ++ "\nD: %2x > ",n); ++ ++ for(i=0;i<16 && n<=max;i++,n++) ++ len += snprintf(page + len, count - len, ++ "%2x ",read_phy_ofdm(dev,n)); ++ ++ // printk("%2x ",read_nic_byte(dev,n)); ++ } ++ len += snprintf(page + len, count - len,"\n"); ++ ++ ++ ++ *eof = 1; ++ return len; ++ ++} ++ ++ ++#if 0 ++static int proc_get_stats_hw(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) ++{ ++ struct net_device *dev = data; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ ++ int len = 0; ++ ++ len += snprintf(page + len, count - len, ++ "NIC int: %lu\n" ++ "Total int: %lu\n", ++ priv->stats.ints, ++ priv->stats.shints); ++ ++ *eof = 1; ++ return len; ++} ++#endif ++ ++static int proc_get_stats_tx(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) ++{ ++ struct net_device *dev = data; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ ++ int len = 0; ++ ++ len += snprintf(page + len, count - len, ++ "TX VI priority ok int: %lu\n" ++ "TX VI priority error int: %lu\n" ++ "TX VO priority ok int: %lu\n" ++ "TX VO priority error int: %lu\n" ++ "TX BE priority ok int: %lu\n" ++ "TX BE priority error int: %lu\n" ++ "TX BK priority ok int: %lu\n" ++ "TX BK priority error int: %lu\n" ++ "TX MANAGE priority ok int: %lu\n" ++ "TX MANAGE priority error int: %lu\n" ++ "TX BEACON priority ok int: %lu\n" ++ "TX BEACON priority error int: %lu\n" ++// "TX high priority ok int: %lu\n" ++// "TX high priority failed error int: %lu\n" ++ "TX queue resume: %lu\n" ++ "TX queue stopped?: %d\n" ++ "TX fifo overflow: %lu\n" ++// "TX beacon: %lu\n" ++ "TX VI queue: %d\n" ++ "TX VO queue: %d\n" ++ "TX BE queue: %d\n" ++ "TX BK queue: %d\n" ++ "TX BEACON queue: %d\n" ++ "TX MANAGE queue: %d\n" ++// "TX HW queue: %d\n" ++ "TX VI dropped: %lu\n" ++ "TX VO dropped: %lu\n" ++ "TX BE dropped: %lu\n" ++ "TX BK dropped: %lu\n" ++ "TX total data packets %lu\n", ++// "TX beacon aborted: %lu\n", ++ priv->stats.txviokint, ++ priv->stats.txvierr, ++ priv->stats.txvookint, ++ priv->stats.txvoerr, ++ priv->stats.txbeokint, ++ priv->stats.txbeerr, ++ priv->stats.txbkokint, ++ priv->stats.txbkerr, ++ priv->stats.txmanageokint, ++ priv->stats.txmanageerr, ++ priv->stats.txbeaconokint, ++ priv->stats.txbeaconerr, ++// priv->stats.txhpokint, ++// priv->stats.txhperr, ++ priv->stats.txresumed, ++ netif_queue_stopped(dev), ++ priv->stats.txoverflow, ++// priv->stats.txbeacon, ++ atomic_read(&(priv->tx_pending[VI_PRIORITY])), ++ atomic_read(&(priv->tx_pending[VO_PRIORITY])), ++ atomic_read(&(priv->tx_pending[BE_PRIORITY])), ++ atomic_read(&(priv->tx_pending[BK_PRIORITY])), ++ atomic_read(&(priv->tx_pending[BEACON_PRIORITY])), ++ atomic_read(&(priv->tx_pending[MANAGE_PRIORITY])), ++// read_nic_byte(dev, TXFIFOCOUNT), ++ priv->stats.txvidrop, ++ priv->stats.txvodrop, ++ priv->stats.txbedrop, ++ priv->stats.txbkdrop, ++ priv->stats.txdatapkt ++// priv->stats.txbeaconerr ++ ); ++ ++ *eof = 1; ++ return len; ++} ++ ++ ++ ++static int proc_get_stats_rx(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) ++{ ++ struct net_device *dev = data; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ ++ int len = 0; ++ ++ len += snprintf(page + len, count - len, ++ "RX packets: %lu\n" ++ "RX urb status error: %lu\n" ++ "RX invalid urb error: %lu\n", ++ priv->stats.rxok, ++ priv->stats.rxstaterr, ++ priv->stats.rxurberr); ++ ++ *eof = 1; ++ return len; ++} ++ ++#if WIRELESS_EXT < 17 ++static struct iw_statistics *r8180_get_wireless_stats(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ return &priv->wstats; ++} ++#endif ++ ++void rtl8180_proc_module_init(void) ++{ ++ DMESG("Initializing proc filesystem"); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) ++ rtl8180_proc=create_proc_entry(RTL8187_MODULE_NAME, S_IFDIR, proc_net); ++#else ++ rtl8180_proc=create_proc_entry(RTL8187_MODULE_NAME, S_IFDIR, init_net.proc_net); ++#endif ++} ++ ++ ++void rtl8180_proc_module_remove(void) ++{ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) ++ remove_proc_entry(RTL8187_MODULE_NAME, proc_net); ++#else ++ remove_proc_entry(RTL8187_MODULE_NAME, init_net.proc_net); ++#endif ++} ++ ++ ++void rtl8180_proc_remove_one(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ if (priv->dir_dev) { ++ // remove_proc_entry("stats-hw", priv->dir_dev); ++ remove_proc_entry("stats-tx", priv->dir_dev); ++ remove_proc_entry("stats-rx", priv->dir_dev); ++ // remove_proc_entry("stats-ieee", priv->dir_dev); ++ remove_proc_entry("stats-ap", priv->dir_dev); ++ remove_proc_entry("registers", priv->dir_dev); ++ remove_proc_entry("cck-registers",priv->dir_dev); ++ remove_proc_entry("ofdm-registers",priv->dir_dev); ++ remove_proc_entry(dev->name, rtl8180_proc); ++ priv->dir_dev = NULL; ++ } ++} ++ ++ ++void rtl8180_proc_init_one(struct net_device *dev) ++{ ++ struct proc_dir_entry *e; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ priv->dir_dev = create_proc_entry(dev->name, ++ S_IFDIR | S_IRUGO | S_IXUGO, ++ rtl8180_proc); ++ if (!priv->dir_dev) { ++ DMESGE("Unable to initialize /proc/net/rtl8187/%s\n", ++ dev->name); ++ return; ++ } ++ #if 0 ++ e = create_proc_read_entry("stats-hw", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_stats_hw, dev); ++ ++ if (!e) { ++ DMESGE("Unable to initialize " ++ "/proc/net/rtl8187/%s/stats-hw\n", ++ dev->name); ++ } ++ #endif ++ e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_stats_rx, dev); ++ ++ if (!e) { ++ DMESGE("Unable to initialize " ++ "/proc/net/rtl8187/%s/stats-rx\n", ++ dev->name); ++ } ++ ++ ++ e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_stats_tx, dev); ++ ++ if (!e) { ++ DMESGE("Unable to initialize " ++ "/proc/net/rtl8187/%s/stats-tx\n", ++ dev->name); ++ } ++ #if 0 ++ e = create_proc_read_entry("stats-ieee", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_stats_ieee, dev); ++ ++ if (!e) { ++ DMESGE("Unable to initialize " ++ "/proc/net/rtl8187/%s/stats-ieee\n", ++ dev->name); ++ } ++ ++ #endif ++ ++ e = create_proc_read_entry("stats-ap", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_stats_ap, dev); ++ ++ if (!e) { ++ DMESGE("Unable to initialize " ++ "/proc/net/rtl8187/%s/stats-ap\n", ++ dev->name); ++ } ++ ++ e = create_proc_read_entry("registers", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_registers, dev); ++ if (!e) { ++ DMESGE("Unable to initialize " ++ "/proc/net/rtl8187/%s/registers\n", ++ dev->name); ++ } ++ ++ e = create_proc_read_entry("cck-registers", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_cck_reg, dev); ++ if (!e) { ++ DMESGE("Unable to initialize " ++ "/proc/net/rtl8187/%s/cck-registers\n", ++ dev->name); ++ } ++ ++ e = create_proc_read_entry("ofdm-registers", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_ofdm_reg, dev); ++ if (!e) { ++ DMESGE("Unable to initialize " ++ "/proc/net/rtl8187/%s/ofdm-registers\n", ++ dev->name); ++ } ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if( priv->mshobj && priv->mshobj->ext_patch_create_proc ) ++ priv->mshobj->ext_patch_create_proc(priv); ++#endif ++ ++} ++/**************************************************************************** ++ -----------------------------MISC STUFF------------------------- ++*****************************************************************************/ ++ ++/* this is only for debugging */ ++void print_buffer(u32 *buffer, int len) ++{ ++ int i; ++ u8 *buf =(u8*)buffer; ++ ++ printk("ASCII BUFFER DUMP (len: %x):\n",len); ++ ++ for(i=0;itx_np_pending : &priv->tx_lp_pending); ++ int used = atomic_read(&priv->tx_pending[priority]); ++ ++ return (used < MAX_TX_URB); ++} ++ ++void tx_timeout(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ //rtl8180_commit(dev); ++ printk("@@@@ Transmit timeout at %ld, latency %ld\n", jiffies, ++ jiffies - dev->trans_start); ++ ++ printk("@@@@ netif_queue_stopped = %d\n", netif_queue_stopped(dev)); ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++ schedule_work(&priv->reset_wq); ++#else ++ schedule_task(&priv->reset_wq); ++#endif ++ //DMESG("TXTIMEOUT"); ++} ++ ++ ++/* this is only for debug */ ++void dump_eprom(struct net_device *dev) ++{ ++ int i; ++ for(i=0; i<63; i++) ++ DMESG("EEPROM addr %x : %x", i, eprom_read(dev,i)); ++} ++ ++/* this is only for debug */ ++void rtl8180_dump_reg(struct net_device *dev) ++{ ++ int i; ++ int n; ++ int max=0xff; ++ ++ DMESG("Dumping NIC register map"); ++ ++ for(n=0;n<=max;) ++ { ++ printk( "\nD: %2x> ", n); ++ for(i=0;i<16 && n<=max;i++,n++) ++ printk("%2x ",read_nic_byte(dev,n)); ++ } ++ printk("\n"); ++} ++ ++/**************************************************************************** ++ ------------------------------HW STUFF--------------------------- ++*****************************************************************************/ ++ ++ ++void rtl8180_irq_enable(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ //priv->irq_enabled = 1; ++ ++ //write_nic_word(dev,INTA_MASK,INTA_RXOK | INTA_RXDESCERR | INTA_RXOVERFLOW | ++ // INTA_TXOVERFLOW | INTA_HIPRIORITYDESCERR | INTA_HIPRIORITYDESCOK | ++ // INTA_NORMPRIORITYDESCERR | INTA_NORMPRIORITYDESCOK | ++ // INTA_LOWPRIORITYDESCERR | INTA_LOWPRIORITYDESCOK | INTA_TIMEOUT); ++ ++ write_nic_word(dev,INTA_MASK, priv->irq_mask); ++} ++ ++ ++void rtl8180_irq_disable(struct net_device *dev) ++{ ++ write_nic_word(dev,INTA_MASK,0); ++ force_pci_posting(dev); ++// priv->irq_enabled = 0; ++} ++ ++ ++void rtl8180_set_mode(struct net_device *dev,int mode) ++{ ++ u8 ecmd; ++ ecmd=read_nic_byte(dev, EPROM_CMD); ++ ecmd=ecmd &~ EPROM_CMD_OPERATING_MODE_MASK; ++ ecmd=ecmd | (mode<ieee80211->state == IEEE80211_LINKED){ ++ ++ if (priv->ieee80211->iw_mode == IW_MODE_INFRA) ++ msr |= (MSR_LINK_MANAGED<ieee80211->iw_mode == IW_MODE_ADHOC) ++ msr |= (MSR_LINK_ADHOC<ieee80211->iw_mode == IW_MODE_MASTER) ++ msr |= (MSR_LINK_MASTER<chan=ch; ++ #if 0 ++ if(priv->ieee80211->iw_mode == IW_MODE_ADHOC || ++ priv->ieee80211->iw_mode == IW_MODE_MASTER){ ++ ++ priv->ieee80211->link_state = WLAN_LINK_ASSOCIATED; ++ priv->ieee80211->master_chan = ch; ++ rtl8180_update_beacon_ch(dev); ++ } ++ #endif ++ ++ /* this hack should avoid frame TX during channel setting*/ ++ tx = read_nic_dword(dev,TX_CONF); ++ tx &= ~TX_LOOPBACK_MASK; ++ ++#ifndef LOOP_TEST ++ write_nic_dword(dev,TX_CONF, tx |( TX_LOOPBACK_MAC<rf_set_chan(dev,priv->chan); ++ //mdelay(10); //CPU occupany is too high. LZM 31/10/2008 ++ write_nic_dword(dev,TX_CONF,tx | (TX_LOOPBACK_NONE<udev, ++ usb_rcvbulkpipe(priv->udev,(NIC_8187 == priv->card_8187)?0x81:0x83), ++ rx_urb->transfer_buffer, ++ RX_URB_SIZE, ++ rtl8187_rx_isr, ++ dev); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ err = usb_submit_urb(rx_urb, GFP_ATOMIC); ++#else ++ err = usb_submit_urb(rx_urb); ++#endif ++ if(err && err != -EPERM){ ++ DMESGE("cannot submit RX command. URB_STATUS %x",rx_urb->status); ++ } ++} ++ ++ ++void rtl8187_rx_manage_urbsubmit(struct net_device *dev, struct urb* rx_urb) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ int err; ++#ifdef THOMAS_BEACON ++ usb_fill_bulk_urb(rx_urb,priv->udev, ++ usb_rcvbulkpipe(priv->udev,0x09), ++ rx_urb->transfer_buffer, ++ rx_urb->transfer_buffer_length, ++ rtl8187_rx_manage_isr, dev); ++#endif ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ err = usb_submit_urb(rx_urb, GFP_ATOMIC); ++#else ++ err = usb_submit_urb(rx_urb); ++#endif ++ if(err && err != -EPERM){ ++ DMESGE("cannot submit RX command. URB_STATUS %x",rx_urb->status); ++ } ++} ++ ++ ++ ++void rtl8187_rx_initiate(struct net_device *dev) ++{ ++ int i; ++ unsigned long flags; ++ struct urb *purb; ++ ++ struct sk_buff *pskb; ++ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ ++ priv->tx_urb_index = 0; ++ ++ if ((!priv->rx_urb) || (!priv->pp_rxskb)) { ++ ++ DMESGE("Cannot intiate RX urb mechanism"); ++ return; ++ ++ } ++ ++ priv->rx_inx = 0; ++#ifdef THOMAS_TASKLET ++ atomic_set(&priv->irt_counter,0); ++#endif ++ for(i = 0;i < MAX_RX_URB; i++){ ++ ++ purb = priv->rx_urb[i] = usb_alloc_urb(0,GFP_KERNEL); ++ ++ if(!priv->rx_urb[i]) ++ goto destroy; ++ ++ pskb = priv->pp_rxskb[i] = dev_alloc_skb (RX_URB_SIZE); ++ ++ if (pskb == NULL) ++ goto destroy; ++ ++ purb->transfer_buffer_length = RX_URB_SIZE; ++ purb->transfer_buffer = pskb->data; ++ } ++ ++ spin_lock_irqsave(&priv->irq_lock,flags);//added by thomas ++ ++ for(i=0;irx_urb[i]); ++ ++ spin_unlock_irqrestore(&priv->irq_lock,flags);//added by thomas ++ ++ return; ++ ++destroy: ++ ++ for(i = 0; i < MAX_RX_URB; i++) { ++ ++ purb = priv->rx_urb[i]; ++ ++ if (purb) ++ usb_free_urb(purb); ++ ++ pskb = priv->pp_rxskb[i]; ++ ++ if (pskb) ++ dev_kfree_skb_any(pskb); ++ ++ } ++ ++ return; ++} ++ ++ ++void rtl8187_rx_manage_initiate(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ if(!priv->rx_urb) ++ DMESGE("Cannot intiate RX urb mechanism"); ++ ++ rtl8187_rx_manage_urbsubmit(dev,priv->rx_urb[MAX_RX_URB]); ++ ++} ++ ++ ++void rtl8187_set_rxconf(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ u32 rxconf; ++ ++ rxconf=read_nic_dword(dev,RX_CONF); ++ rxconf = rxconf &~ MAC_FILTER_MASK; ++ rxconf = rxconf | (1<EEPROMCSMethod;//for antenna ++#endif ++ ++ if (dev->flags & IFF_PROMISC) DMESG ("NIC in promisc mode"); ++ ++ if(priv->ieee80211->iw_mode == IW_MODE_MONITOR || \ ++ dev->flags & IFF_PROMISC){ ++ rxconf = rxconf | (1<ieee80211->iw_mode == IW_MODE_MASTER){ ++ rxconf = rxconf | (1<ieee80211->iw_mode == IW_MODE_MONITOR){ ++ rxconf = rxconf | (1<crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR) ++ rxconf = rxconf | (1<card_8187) { ++ cmd=read_nic_byte(dev,CMD); ++ write_nic_byte(dev,CMD,cmd | (1<ReceiveConfig); ++ } ++} ++ ++ ++void rtl8180_tx_enable(struct net_device *dev) ++{ ++ u8 cmd; ++ u8 byte; ++ u32 txconf = 0; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ ++ if(NIC_8187B == priv->card_8187){ ++ write_nic_dword(dev, TCR, priv->TransmitConfig); ++ byte = read_nic_byte(dev, MSR); ++ byte |= MSR_LINK_ENEDCA; ++ write_nic_byte(dev, MSR, byte); ++#ifdef LOOP_TEST ++ txconf= read_nic_dword(dev,TX_CONF); ++ txconf = txconf | (TX_LOOPBACK_MAC<retry_data<retry_rts<dma_poll_mask &=~(1<dma_poll_mask); ++ rtl8180_set_mode(dev,EPROM_CMD_NORMAL); ++} ++ ++ ++void rtl8180_ ++_disable(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ priv->dma_poll_mask |= (1<dma_poll_mask); ++ rtl8180_set_mode(dev,EPROM_CMD_NORMAL); ++} ++ ++#endif ++ ++ ++void rtl8180_rtx_disable(struct net_device *dev) ++{ ++ u8 cmd; ++ int i; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ cmd=read_nic_byte(dev,CMD); ++ write_nic_byte(dev, CMD, cmd &~ \ ++ ((1<rx_inx;//0 ++ i=0; ++ if(priv->rx_urb){ ++ while(irx_urb[index]){ ++ usb_kill_urb(priv->rx_urb[index]); ++ } ++ if( index == (MAX_RX_URB-1) ) ++ index=0; ++ else ++ index=index+1; ++ i++; ++ } ++ if(priv->rx_urb[MAX_RX_URB]) ++ usb_kill_urb(priv->rx_urb[MAX_RX_URB]); ++ } ++ } ++#endif ++} ++ ++ ++int alloc_tx_beacon_desc_ring(struct net_device *dev, int count) ++{ ++ #if 0 ++ int i; ++ u32 *tmp; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ ++ priv->txbeaconring = (u32*)pci_alloc_consistent(priv->pdev, ++ sizeof(u32)*8*count, ++ &priv->txbeaconringdma); ++ if (!priv->txbeaconring) return -1; ++ for (tmp=priv->txbeaconring,i=0;itxbeaconringdma+((i+1)*8*4); ++ else ++ *(tmp+4) = (u32)priv->txbeaconringdma; ++ ++ tmp=tmp+8; ++ } ++ #endif ++ return 0; ++} ++ ++long NetgearSignalStrengthTranslate(long LastSS,long CurrSS) ++{ ++ long RetSS; ++ ++ // Step 1. Scale mapping. ++ if(CurrSS >= 71 && CurrSS <= 100){ ++ RetSS = 90 + ((CurrSS - 70) / 3); ++ }else if(CurrSS >= 41 && CurrSS <= 70){ ++ RetSS = 78 + ((CurrSS - 40) / 3); ++ }else if(CurrSS >= 31 && CurrSS <= 40){ ++ RetSS = 66 + (CurrSS - 30); ++ }else if(CurrSS >= 21 && CurrSS <= 30){ ++ RetSS = 54 + (CurrSS - 20); ++ }else if(CurrSS >= 5 && CurrSS <= 20){ ++ RetSS = 42 + (((CurrSS - 5) * 2) / 3); ++ }else if(CurrSS == 4){ ++ RetSS = 36; ++ }else if(CurrSS == 3){ ++ RetSS = 27; ++ }else if(CurrSS == 2){ ++ RetSS = 18; ++ }else if(CurrSS == 1){ ++ RetSS = 9; ++ }else{ ++ RetSS = CurrSS; ++ } ++ //RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS)); ++ ++ // Step 2. Smoothing. ++ if(LastSS > 0){ ++ RetSS = ((LastSS * 5) + (RetSS)+ 5) / 6; ++ } ++ //RT_TRACE(COMP_DBG, DBG_LOUD, ("$$$$$ After Smoothing: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS)); ++ ++ return RetSS; ++} ++ ++extern long TranslateToDbm8187(u8 SignalStrengthIndex); // 0-100 index. ++//long TranslateToDbm8187(u8 SignalStrengthIndex) // 0-100 index. ++//{ ++ // long SignalPower; // in dBm. ++ ++ // Translate to dBm (x=0.5y-95). ++ // SignalPower = (long)((SignalStrengthIndex + 1) >> 1); ++ // SignalPower -= 95; ++ ++ // return SignalPower; ++//} ++ ++ ++void rtl8180_reset(struct net_device *dev) ++{ ++ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u8 cr; ++ int i; ++ ++ ++ /* make sure the analog power is on before ++ * reset, otherwise reset may fail ++ */ ++ if(NIC_8187 == priv->card_8187) { ++ rtl8180_set_anaparam(dev, RTL8225_ANAPARAM_ON); ++ rtl8185_set_anaparam2(dev, RTL8225_ANAPARAM2_ON); ++ rtl8180_irq_disable(dev); ++ mdelay(200); ++ write_nic_byte_E(dev,0x18,0x10); ++ write_nic_byte_E(dev,0x18,0x11); ++ write_nic_byte_E(dev,0x18,0x00); ++ mdelay(200); ++ } ++ ++ ++ cr=read_nic_byte(dev,CMD); ++ cr = cr & 2; ++ cr = cr | (1<card_8187) { ++ ++ //printk("This is RTL8187 Reset procedure\n"); ++ rtl8180_set_mode(dev,EPROM_CMD_LOAD); ++ force_pci_posting(dev); ++ mdelay(200); ++ ++ /* after the eeprom load cycle, make sure we have ++ * correct anaparams ++ */ ++ rtl8180_set_anaparam(dev, RTL8225_ANAPARAM_ON); ++ rtl8185_set_anaparam2(dev, RTL8225_ANAPARAM2_ON); ++ } ++ else { ++ //printk("This is RTL8187B Reset procedure\n"); ++ //test pending bug, john 20070815 ++ //initialize tx_pending ++ for(i=0;i<0x10;i++) atomic_set(&(priv->tx_pending[i]), 0); ++ ++ } ++ ++} ++ ++inline u16 ieeerate2rtlrate(int rate) ++{ ++ switch(rate){ ++ case 10: ++ return 0; ++ case 20: ++ return 1; ++ case 55: ++ return 2; ++ case 110: ++ return 3; ++ case 60: ++ return 4; ++ case 90: ++ return 5; ++ case 120: ++ return 6; ++ case 180: ++ return 7; ++ case 240: ++ return 8; ++ case 360: ++ return 9; ++ case 480: ++ return 10; ++ case 540: ++ return 11; ++ default: ++ return 3; ++ ++ } ++} ++static u16 rtl_rate[] = {10,20,55,110,60,90,120,180,240,360,480,540,720}; ++inline u16 rtl8180_rate2rate(short rate) ++{ ++ if (rate >12) return 10; ++ return rtl_rate[rate]; ++} ++ ++void rtl8180_irq_rx_tasklet(struct r8180_priv *priv); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++void rtl8187_rx_isr(struct urb *rx_urb, struct pt_regs *regs) ++#else ++void rtl8187_rx_isr(struct urb* rx_urb) ++#endif ++{ ++ struct net_device *dev = (struct net_device*)rx_urb->context; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ priv->rxurb_task = rx_urb; ++ ++ ++ //DMESGW("David: Rx tasklet start!"); ++ ++#ifdef THOMAS_TASKLET ++ atomic_inc( &priv->irt_counter ); ++ ++ //if( likely(priv->irt_counter_head+1 != priv->irt_counter_tail) ){ ++ // priv->irt_counter_head = (priv->irt_counter_head+1)&0xffff ; ++ tasklet_schedule(&priv->irq_rx_tasklet); ++ //} else{ ++ //DMESG("error: priv->irt_counter_head is going to pass through priv->irt_counter_tail\n"); ++ /* ++ skb = priv->pp_rxskb[priv->rx_inx]; ++ dev_kfree_skb_any(skb); ++ ++ skb = dev_alloc_skb(RX_URB_SIZE); ++ if (skb == NULL) ++ panic("No Skb For RX!/n"); ++ ++ rx_urb->transfer_buffer = skb->data; ++ ++ priv->pp_rxskb[priv->rx_inx] = skb; ++ if(status == 0) ++ rtl8187_rx_urbsubmit(dev,rx_urb); ++ else { ++ priv->pp_rxskb[priv->rx_inx] = NULL; ++ dev_kfree_skb_any(skb); ++ printk("RX process aborted due to explicit shutdown (%x) ", status); ++ } ++ ++ if (*prx_inx == (MAX_RX_URB -1)) ++ *prx_inx = 0; ++ else ++ *prx_inx = *prx_inx + 1; ++ ++ */ ++ //} ++#endif ++ ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++void rtl8187_rx_manage_isr(struct urb *rx_urb, struct pt_regs *regs) ++#else ++void rtl8187_rx_manage_isr(struct urb* rx_urb) ++#endif ++{ ++ struct net_device *dev = (struct net_device*)rx_urb->context; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int status,cmd; ++ struct sk_buff *skb; ++ u32 *desc; ++ int ret; ++ unsigned long flag; ++ ++ //DMESG("RX %d ",rx_urb->status); ++ status = rx_urb->status; ++ if(status == 0){ ++ ++ desc = (u32*)(rx_urb->transfer_buffer); ++ cmd = (desc[0] >> 30) & 0x03; ++ //printk(KERN_ALERT "buffersize = %d, length = %d, pipe = %p\n", ++ //rx_urb->transfer_buffer_length, rx_urb->actual_length, rx_urb->pipe>>15); ++ ++ if(cmd == 0x00) {//beacon interrupt ++ //send beacon packet ++ ++ spin_lock_irqsave(&priv->ieee80211->beaconflag_lock,flag); ++ if(priv->flag_beacon == true){ ++ //printk("rtl8187_rx_manage_isr(): CMD_TYPE0_BCN_INTR\n"); ++ ++ skb = ieee80211_get_beacon(priv->ieee80211); ++ if(!skb){ ++ DMESG("not enought memory for allocating beacon"); ++ return; ++ } ++ //printk(KERN_WARNING "to send beacon packet through beacon endpoint!\n"); ++ ret = rtl8180_tx(dev, (u32*)skb->data, skb->len, BEACON_PRIORITY, ++ 0, ieeerate2rtlrate(priv->ieee80211->basic_rate)); ++ ++ if( ret != 0 ){ ++ printk(KERN_ALERT "tx beacon packet error : %d !\n", ret); ++ } ++ dev_kfree_skb_any(skb); ++ ++ //} else {//0x00 ++ //{ log the device information ++ // At present, It is not implemented just now. ++ //} ++ //} ++ ++ } ++ spin_unlock_irqrestore(&priv->ieee80211->beaconflag_lock,flag); ++ } ++ else if(cmd == 0x01){ ++ //printk("rtl8187_rx_manage_isr(): CMD_TYPE1_TX_CLOSE\n"); ++ priv->CurrRetryCnt += (u16)desc[0]&0x000000ff; ++ //printk("priv->CurrRetryCnt is %d\n",priv->CurrRetryCnt); ++ } ++ else ++ printk("HalUsbInCommandComplete8187B(): unknown Type(%#X) !!!\n", cmd); ++ ++ }else{ ++ priv->stats.rxstaterr++; ++ priv->ieee80211->stats.rx_errors++; ++ } ++ ++ ++ if( status == 0 ) ++ //if(status != -ENOENT) ++ rtl8187_rx_manage_urbsubmit(dev, rx_urb); ++ else ++ ;//DMESG("Mangement RX process aborted due to explicit shutdown"); ++} ++ ++#if 0 ++void rtl8180_tx_queues_stop(struct net_device *dev) ++{ ++ //struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ u8 dma_poll_mask = (1<dma_poll_mask |= (1<dma_poll_mask); ++ rtl8180_set_mode(dev,EPROM_CMD_NORMAL); ++ #endif ++} ++ ++ ++void rtl8180_data_hard_resume(struct net_device *dev) ++{ ++ // FIXME !! ++ #if 0 ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ priv->dma_poll_mask &= ~(1<dma_poll_mask); ++ rtl8180_set_mode(dev,EPROM_CMD_NORMAL); ++ #endif ++} ++ ++unsigned int PRI2EP[4] = {0x06,0x07,0x05,0x04}; ++// this function TX data frames when the ieee80211 stack requires this. ++// It checks also if we need to stop the ieee tx queue, eventually do it ++void rtl8180_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ ++ short morefrag = 0; ++ unsigned long flags; ++ struct ieee80211_hdr *h = (struct ieee80211_hdr *) skb->data; ++ ++ unsigned char ep; ++ short ret; //john ++ ++ if (le16_to_cpu(h->frame_ctl) & IEEE80211_FCTL_MOREFRAGS) ++ morefrag = 1; ++ //DMESG("%x %x", h->frame_ctl, h->seq_ctl); ++ /* ++ * This function doesn't require lock because we make ++ * sure it's called with the tx_lock already acquired. ++ * this come from the kernel's hard_xmit callback (trought ++ * the ieee stack, or from the try_wake_queue (again trought ++ * the ieee stack. ++ */ ++ spin_lock_irqsave(&priv->tx_lock,flags); ++ ++ //lzm mod 20081128 for sometimes wlan down but it still have some pkt to tx ++ if((priv->ieee80211->bHwRadioOff)||(!priv->up)) ++ { ++ spin_unlock_irqrestore(&priv->tx_lock,flags); ++ ++ return; ++ } ++ ++ if(NIC_8187B == priv->card_8187){ ++ ep = PRI2EP[skb->priority]; ++ } else { ++ ep = LOW_PRIORITY; ++ } ++ //if (!check_nic_enought_desc(dev, PRI2EP[skb->priority])){ ++ if (!check_nic_enought_desc(dev, ep)){ ++ DMESG("Error: no TX slot "); ++ ieee80211_stop_queue(priv->ieee80211); ++ } ++ ++#ifdef LED_SHIN ++ priv->ieee80211->ieee80211_led_contorl(dev,LED_CTL_TX); ++#endif ++ ++ ret = rtl8180_tx(dev, (u32*)skb->data, skb->len, ep, morefrag,ieeerate2rtlrate(rate)); ++ if(ret!=0) DMESG("Error: rtl8180_tx failed in rtl8180_hard_data_xmit\n");//john ++ ++ priv->stats.txdatapkt++; ++ ++ //if (!check_nic_enought_desc(dev, PRI2EP[skb->priority])){ ++ if (!check_nic_enought_desc(dev, ep)){ ++ ieee80211_stop_queue(priv->ieee80211); ++ } ++ ++ spin_unlock_irqrestore(&priv->tx_lock,flags); ++ ++} ++ ++//This is a rough attempt to TX a frame ++//This is called by the ieee 80211 stack to TX management frames. ++//If the ring is full packet are dropped (for data frame the queue ++//is stopped before this can happen). ++ ++int rtl8180_hard_start_xmit(struct sk_buff *skb,struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct ieee80211_device *ieee = priv->ieee80211; ++ int ret; ++ unsigned long flags; ++ spin_lock_irqsave(&priv->tx_lock,flags); ++ ++ //lzm mod 20081128 for sometimes wlan down but it still have some pkt to tx ++ if((priv->ieee80211->bHwRadioOff)||(!priv->up)) ++ { ++ spin_unlock_irqrestore(&priv->tx_lock,flags); ++ return 0; ++ } ++ ++ ret = rtl8180_tx(dev, (u32*)skb->data, skb->len, MANAGE_PRIORITY, 0, ieeerate2rtlrate(ieee->basic_rate)); ++ ++ priv->ieee80211->stats.tx_bytes+=skb->len; ++ priv->ieee80211->stats.tx_packets++; ++ ++ spin_unlock_irqrestore(&priv->tx_lock,flags); ++ ++ return ret; ++} ++ ++ ++#if 0 ++// longpre 144+48 shortpre 72+24 ++u16 rtl8180_len2duration(u32 len, short rate,short* ext) ++{ ++ u16 duration; ++ u16 drift; ++ *ext=0; ++ ++ switch(rate){ ++ case 0://1mbps ++ *ext=0; ++ duration = ((len+4)<<4) /0x2; ++ drift = ((len+4)<<4) % 0x2; ++ if(drift ==0 ) break; ++ duration++; ++ break; ++ ++ case 1://2mbps ++ *ext=0; ++ duration = ((len+4)<<4) /0x4; ++ drift = ((len+4)<<4) % 0x4; ++ if(drift ==0 ) break; ++ duration++; ++ break; ++ ++ case 2: //5.5mbps ++ *ext=0; ++ duration = ((len+4)<<4) /0xb; ++ drift = ((len+4)<<4) % 0xb; ++ if(drift ==0 ) ++ break; ++ duration++; ++ break; ++ ++ default: ++ case 3://11mbps ++ *ext=0; ++ duration = ((len+4)<<4) /0x16; ++ drift = ((len+4)<<4) % 0x16; ++ if(drift ==0 ) ++ break; ++ duration++; ++ if(drift > 6) ++ break; ++ *ext=1; ++ break; ++ } ++ ++ return duration; ++} ++#endif ++ ++void rtl8180_try_wake_queue(struct net_device *dev, int pri); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++void rtl8187_lptx_isr(struct urb *tx_urb, struct pt_regs *regs) ++#else ++void rtl8187_lptx_isr(struct urb* tx_urb) ++#endif ++{ ++ struct net_device *dev = (struct net_device*)tx_urb->context; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(tx_urb->status == 0){ ++ dev->trans_start = jiffies; //john ++ priv->stats.txlpokint++; ++ priv->txokbytestotal+=tx_urb->actual_length; ++ }else{ ++ priv->stats.txlperr++; ++ } ++ ++ kfree(tx_urb->transfer_buffer); ++ usb_free_urb(tx_urb); ++ ++ if(atomic_read(&priv->tx_pending[LOW_PRIORITY]) >= 1) ++ atomic_dec(&priv->tx_pending[LOW_PRIORITY]); ++ ++ rtl8180_try_wake_queue(dev,LOW_PRIORITY); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++void rtl8187_nptx_isr(struct urb *tx_urb, struct pt_regs *regs) ++#else ++void rtl8187_nptx_isr(struct urb* tx_urb) ++#endif ++{ ++ struct net_device *dev = (struct net_device*)tx_urb->context; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(tx_urb->status == 0){ ++ dev->trans_start = jiffies; //john ++ priv->stats.txnpokint++; ++ }else{ ++ priv->stats.txnperr++; ++ } ++ ++ kfree(tx_urb->transfer_buffer); ++ usb_free_urb(tx_urb); ++ ++ if(atomic_read(&priv->tx_pending[NORM_PRIORITY]) >= 1) ++ atomic_dec(&priv->tx_pending[NORM_PRIORITY]); ++ //rtl8180_try_wake_queue(dev,NORM_PRIORITY); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++void rtl8187_votx_isr(struct urb *tx_urb, struct pt_regs *regs) ++#else ++void rtl8187_votx_isr(struct urb* tx_urb) ++#endif ++{ ++ struct net_device *dev = (struct net_device*)tx_urb->context; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(tx_urb->status == 0){ ++ dev->trans_start = jiffies; //john ++ priv->stats.txvookint++; ++ priv->txokbytestotal+=tx_urb->actual_length; ++ }else{ ++ priv->stats.txvoerr++; ++ } ++ ++ kfree(tx_urb->transfer_buffer); ++ usb_free_urb(tx_urb); ++ ++ if(atomic_read(&priv->tx_pending[VO_PRIORITY]) >= 1) ++ atomic_dec(&priv->tx_pending[VO_PRIORITY]); ++ rtl8180_try_wake_queue(dev,VO_PRIORITY); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++void rtl8187_vitx_isr(struct urb *tx_urb, struct pt_regs *regs) ++#else ++void rtl8187_vitx_isr(struct urb* tx_urb) ++#endif ++{ ++ struct net_device *dev = (struct net_device*)tx_urb->context; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(tx_urb->status == 0){ ++ dev->trans_start = jiffies; //john ++ priv->stats.txviokint++; ++ priv->txokbytestotal+=tx_urb->actual_length; ++ }else{ ++ priv->stats.txvierr++; ++ } ++ ++ kfree(tx_urb->transfer_buffer); ++ usb_free_urb(tx_urb); ++ ++ if(atomic_read(&priv->tx_pending[VI_PRIORITY]) >= 1) ++ atomic_dec(&priv->tx_pending[VI_PRIORITY]); ++ rtl8180_try_wake_queue(dev,VI_PRIORITY); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++void rtl8187_betx_isr(struct urb *tx_urb, struct pt_regs *regs) ++#else ++void rtl8187_betx_isr(struct urb* tx_urb) ++#endif ++{ ++ struct net_device *dev = (struct net_device*)tx_urb->context; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(tx_urb->status == 0){ ++ dev->trans_start = jiffies; //john ++ priv->stats.txbeokint++; ++ priv->txokbytestotal+=tx_urb->actual_length; ++ }else{ ++ priv->stats.txbeerr++; ++ } ++ ++ kfree(tx_urb->transfer_buffer); ++ usb_free_urb(tx_urb); ++ ++ if(atomic_read(&priv->tx_pending[BE_PRIORITY]) >= 1) ++ atomic_dec(&priv->tx_pending[BE_PRIORITY]); ++ rtl8180_try_wake_queue(dev, BE_PRIORITY); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++void rtl8187_bktx_isr(struct urb *tx_urb, struct pt_regs *regs) ++#else ++void rtl8187_bktx_isr(struct urb* tx_urb) ++#endif ++{ ++ struct net_device *dev = (struct net_device*)tx_urb->context; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(tx_urb->status == 0){ ++ dev->trans_start = jiffies; //john ++ priv->stats.txbkokint++; ++ }else{ ++ priv->stats.txbkerr++; ++ } ++ ++ kfree(tx_urb->transfer_buffer); ++ usb_free_urb(tx_urb); ++ ++ if(atomic_read(&priv->tx_pending[BK_PRIORITY]) >= 1) ++ atomic_dec(&priv->tx_pending[BK_PRIORITY]); ++ rtl8180_try_wake_queue(dev,BK_PRIORITY); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++void rtl8187_beacontx_isr(struct urb *tx_urb, struct pt_regs *regs) ++#else ++void rtl8187_beacontx_isr(struct urb* tx_urb) ++#endif ++{ ++ struct net_device *dev = (struct net_device*)tx_urb->context; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(tx_urb->status == 0){ ++ dev->trans_start = jiffies; //john ++ priv->stats.txbeaconokint++; ++ priv->txokbytestotal+=tx_urb->actual_length; ++ }else{ ++ priv->stats.txbeaconerr++; ++ } ++ ++ kfree(tx_urb->transfer_buffer); ++ usb_free_urb(tx_urb); ++ ++ if(atomic_read(&priv->tx_pending[BEACON_PRIORITY]) >= 1) ++ atomic_dec(&priv->tx_pending[BEACON_PRIORITY]); ++ //rtl8180_try_wake_queue(dev,BEACON_PRIORITY); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++void rtl8187_managetx_isr(struct urb *tx_urb, struct pt_regs *regs) ++#else ++void rtl8187_managetx_isr(struct urb* tx_urb) ++#endif ++{ ++ struct net_device *dev = (struct net_device*)tx_urb->context; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(tx_urb->status == 0){ ++ dev->trans_start = jiffies; //john ++ priv->stats.txmanageokint++; ++ priv->txokbytestotal+=tx_urb->actual_length; ++ }else{ ++ priv->stats.txmanageerr++; ++ } ++ ++ kfree(tx_urb->transfer_buffer); ++ usb_free_urb(tx_urb); ++ ++ if(atomic_read(&priv->tx_pending[MANAGE_PRIORITY]) >= 1) ++ atomic_dec(&priv->tx_pending[MANAGE_PRIORITY]); ++// rtl8180_try_wake_queue(dev,MANAGE_PRIORITY); ++} ++ ++void rtl8187_beacon_stop(struct net_device *dev) ++{ ++ u8 msr, msrm, msr2; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ unsigned long flag; ++ msr = read_nic_byte(dev, MSR); ++ msrm = msr & MSR_LINK_MASK; ++ msr2 = msr & ~MSR_LINK_MASK; ++ if(NIC_8187B == priv->card_8187) { ++ spin_lock_irqsave(&priv->ieee80211->beaconflag_lock,flag); ++ priv->flag_beacon = false; ++ spin_unlock_irqrestore(&priv->ieee80211->beaconflag_lock,flag); ++ } ++ if ((msrm == (MSR_LINK_ADHOC<ieee80211->current_network; ++ ++ ++ write_nic_dword(dev,BSSID,((u32*)net->bssid)[0]); ++ write_nic_word(dev,BSSID+4,((u16*)net->bssid)[2]); ++ ++ rtl8180_update_msr(dev); ++ ++ //rtl8180_set_mode(dev,EPROM_CMD_CONFIG); ++ write_nic_word(dev, AtimWnd, 2); ++ write_nic_word(dev, AtimtrItv, 100); ++ write_nic_word(dev, BEACON_INTERVAL, net->beacon_interval); ++ //write_nic_word(dev, BcnIntTime, 100); ++ write_nic_word(dev, BcnIntTime, 0x3FF); ++ ++ ++} ++ ++void rtl8187_beacon_tx(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ struct sk_buff *skb; ++ int i = 0; ++ u8 cr; ++ unsigned long flag; ++ rtl8187_net_update(dev); ++ ++ if(NIC_8187B == priv->card_8187) { ++ //Cause TSF timer of MAC reset to 0 ++ cr=read_nic_byte(dev,CMD); ++ cr = cr | (1<ieee80211->beaconflag_lock,flag); ++ priv->flag_beacon = true; ++ spin_unlock_irqrestore(&priv->ieee80211->beaconflag_lock,flag); ++ ++ //rtl8187_rx_manage_initiate(dev); ++ } else { ++ printk(KERN_WARNING "get the beacon!\n"); ++ skb = ieee80211_get_beacon(priv->ieee80211); ++ if(!skb){ ++ DMESG("not enought memory for allocating beacon"); ++ return; ++ } ++ ++ write_nic_byte(dev, BQREQ, read_nic_byte(dev, BQREQ) | (1<<7)); ++ ++ i=0; ++ //while(!read_nic_byte(dev,BQREQ & (1<<7))) ++ while( (read_nic_byte(dev, BQREQ) & (1<<7)) == 0 ) ++ { ++ msleep_interruptible_rtl(HZ/2); ++ if(i++ > 10){ ++ DMESGW("get stuck to wait HW beacon to be ready"); ++ return ; ++ } ++ } ++ //tx ++ rtl8180_tx(dev, (u32*)skb->data, skb->len, NORM_PRIORITY, ++ 0, ieeerate2rtlrate(priv->ieee80211->basic_rate)); ++ if(skb) ++ dev_kfree_skb_any(skb); ++ } ++} ++ ++#if 0 ++void rtl8187_nptx_isr(struct urb *tx_urb, struct pt_regs *regs) ++{ ++ struct net_device *dev = (struct net_device*)tx_urb->context; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if(tx_urb->status == 0) ++ priv->stats.txnpokint++; ++ else ++ priv->stats.txnperr++; ++ kfree(tx_urb->transfer_buffer); ++ usb_free_urb(tx_urb); ++ atomic_dec(&priv->tx_np_pending); ++ //rtl8180_try_wake_queue(dev,NORM_PRIORITY); ++} ++#endif ++inline u8 rtl8180_IsWirelessBMode(u16 rate) ++{ ++ if( ((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220) ) ++ return 1; ++ else return 0; ++} ++ ++u16 N_DBPSOfRate(u16 DataRate); ++ ++u16 ComputeTxTime( ++ u16 FrameLength, ++ u16 DataRate, ++ u8 bManagementFrame, ++ u8 bShortPreamble ++ ) ++{ ++ u16 FrameTime; ++ u16 N_DBPS; ++ u16 Ceiling; ++ ++ if( rtl8180_IsWirelessBMode(DataRate) ) ++ { ++ if( bManagementFrame || !bShortPreamble || DataRate == 10 ){ // long preamble ++ FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10))); ++ }else{ // Short preamble ++ FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10))); ++ } ++ if( ( FrameLength*8 % (DataRate/10) ) != 0 ) //Get the Ceilling ++ FrameTime ++; ++ } else { //802.11g DSSS-OFDM PLCP length field calculation. ++ N_DBPS = N_DBPSOfRate(DataRate); ++ Ceiling = (16 + 8*FrameLength + 6) / N_DBPS ++ + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0); ++ FrameTime = (u16)(16 + 4 + 4*Ceiling + 6); ++ } ++ return FrameTime; ++} ++ ++u16 N_DBPSOfRate(u16 DataRate) ++{ ++ u16 N_DBPS = 24; ++ ++ switch(DataRate) ++ { ++ case 60: ++ N_DBPS = 24; ++ break; ++ ++ case 90: ++ N_DBPS = 36; ++ break; ++ ++ case 120: ++ N_DBPS = 48; ++ break; ++ ++ case 180: ++ N_DBPS = 72; ++ break; ++ ++ case 240: ++ N_DBPS = 96; ++ break; ++ ++ case 360: ++ N_DBPS = 144; ++ break; ++ ++ case 480: ++ N_DBPS = 192; ++ break; ++ ++ case 540: ++ N_DBPS = 216; ++ break; ++ ++ default: ++ break; ++ } ++ ++ return N_DBPS; ++} ++// NOte!!! ++// the rate filled in is the rtl_rate. ++// while the priv->ieee80211->basic_rate,used in the following code is ieee80211 rate. ++ ++#ifdef JUST_FOR_87SEMESH ++#define ActionHeadLen 30 ++#endif ++#define sCrcLng 4 ++#define sAckCtsLng 112 // bits in ACK and CTS frames ++short rtl8180_tx(struct net_device *dev, u32* txbuf, int len, priority_t priority, ++ short morefrag, short rate) ++{ ++ u32 *tx; ++ int pend ; ++ int status; ++ struct urb *tx_urb; ++ int urb_len; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ struct ieee80211_hdr_3addr_QOS *frag_hdr = (struct ieee80211_hdr_3addr_QOS *)txbuf; ++ struct ieee80211_device *ieee;//added for descriptor ++ u8 dest[ETH_ALEN]; ++ ++ bool bUseShortPreamble = false; ++ bool bCTSEnable = false; ++ bool bRTSEnable = false; ++ u16 Duration = 0; ++ u16 RtsDur = 0; ++ u16 ThisFrameTime = 0; ++ u16 TxDescDuration = 0; ++ ++ ieee = priv->ieee80211; ++#if 0 ++//{added by david for filter the packet listed in the filter table ++#ifdef _RTL8187_EXT_PATCH_ ++ if((ieee->iw_mode == ieee->iw_ext_mode) && (ieee->ext_patch_ieee80211_acl_query)) ++ { ++ if(!ieee->ext_patch_ieee80211_acl_query(ieee, frag_hdr->addr1)) { ++ return 0; ++ } ++ } ++#endif ++//} ++#endif ++ ++#ifdef JUST_FOR_87SEMESH ++//#ifdef Lawrence_Mesh ++ u8* meshtype = (u8*)txbuf; ++ if(*meshtype == 0xA8) ++ { ++ //overflow?? ++ //memcpy(meshtype+ActionHeadLen+2,meshtype+ActionHeadLen,Len-ActionHeadLen); ++ //memcpy(meshtype+ActionHeadLen,0,2); ++ u8 actionframe[256]; ++ memset(actionframe,0,256); ++ memcpy(actionframe,meshtype,ActionHeadLen); ++ memcpy(actionframe+ActionHeadLen+2,meshtype+ActionHeadLen,len-ActionHeadLen); ++ txbuf = (u32*)actionframe; ++ len=len+2; ++ frag_hdr = (struct ieee80211_hdr_3addr_QOS *)txbuf; ++ } ++#endif ++ ++ //pend = atomic_read((priority == NORM_PRIORITY)? &priv->tx_np_pending : &priv->tx_lp_pending); ++ pend = atomic_read(&priv->tx_pending[priority]); ++ /* we are locked here so the two atomic_read and inc are executed without interleaves */ ++ if( pend > MAX_TX_URB){ ++ if(NIC_8187 == priv->card_8187) { ++ if(priority == NORM_PRIORITY) ++ priv->stats.txnpdrop++; ++ else ++ priv->stats.txlpdrop++; ++ ++ } else { ++ switch (priority) { ++ case VO_PRIORITY: ++ priv->stats.txvodrop++; ++ break; ++ case VI_PRIORITY: ++ priv->stats.txvidrop++; ++ break; ++ case BE_PRIORITY: ++ priv->stats.txbedrop++; ++ break; ++ case MANAGE_PRIORITY: //lzm for MANAGE_PRIORITY pending ++ if(priv->commit == 0) ++ { ++ priv->commit = 1; ++ printk(KERN_INFO "manage pkt pending will commit now....\n"); ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++ schedule_work(&priv->reset_wq); ++#else ++ schedule_task(&priv->reset_wq); ++#endif ++ } ++ break; ++ default://BK_PRIORITY ++ priv->stats.txbkdrop++; ++ break; ++ } ++ } ++ //printk(KERN_INFO "tx_pending: %d > MAX_TX_URB\n", priority); ++ return -1; ++ } ++ ++ urb_len = len + ((NIC_8187 == priv->card_8187)?(4*3):(4*8)); ++ if((0 == (urb_len&63))||(0 == (urb_len&511))) { ++ urb_len += 1; ++ } ++ ++ tx = kmalloc(urb_len, GFP_ATOMIC); ++ if(!tx) return -ENOMEM; ++ memset(tx, 0, sizeof(u32) * 8); ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ tx_urb = usb_alloc_urb(0,GFP_ATOMIC); ++#else ++ tx_urb = usb_alloc_urb(0); ++#endif ++ ++ if(!tx_urb){ ++ kfree(tx); ++ return -ENOMEM; ++ } ++ ++ // Check multicast/broadcast ++ if (ieee->iw_mode == IW_MODE_INFRA) { ++ /* To DS: Addr1 = BSSID, Addr2 = SA, ++ Addr3 = DA */ ++ //memcpy(&dest, frag_hdr->addr3, ETH_ALEN); ++ memcpy(&dest, frag_hdr->addr1, ETH_ALEN); ++ } else if (ieee->iw_mode == IW_MODE_ADHOC) { ++ /* not From/To DS: Addr1 = DA, Addr2 = SA, ++ Addr3 = BSSID */ ++ memcpy(&dest, frag_hdr->addr1, ETH_ALEN); ++ } ++ ++ if (is_multicast_ether_addr(dest) ||is_broadcast_ether_addr(dest)) ++ { ++ Duration = 0; ++ RtsDur = 0; ++ bRTSEnable = false; ++ bCTSEnable = false; ++ ++ ThisFrameTime = ComputeTxTime(len + sCrcLng, rtl8180_rate2rate(rate), false, bUseShortPreamble); ++ TxDescDuration = ThisFrameTime; ++ } else {// Unicast packet ++ //u8 AckRate; ++ u16 AckTime; ++ ++ // Figure out ACK rate according to BSS basic rate and Tx rate, 2006.03.08 by rcnjko. ++ //AckRate = ComputeAckRate( pMgntInfo->mBrates, (u1Byte)(pTcb->DataRate) ); ++ // Figure out ACK time according to the AckRate and assume long preamble is used on receiver, 2006.03.08, by rcnjko. ++ //AckTime = ComputeTxTime( sAckCtsLng/8, AckRate, FALSE, FALSE); ++ //For simplicity, just use the 1M basic rate ++ AckTime = ComputeTxTime(14, 10,false, false); // AckCTSLng = 14 use 1M bps send ++ //AckTime = ComputeTxTime(14, 2,false, false); // AckCTSLng = 14 use 1M bps send ++ ++ if ( ((len + sCrcLng) > priv->rts) && priv->rts ){ // RTS/CTS. ++ u16 RtsTime, CtsTime; ++ //u16 CtsRate; ++ bRTSEnable = true; ++ bCTSEnable = false; ++ ++ // Rate and time required for RTS. ++ RtsTime = ComputeTxTime( sAckCtsLng/8,priv->ieee80211->basic_rate, false, false); ++ // Rate and time required for CTS. ++ CtsTime = ComputeTxTime(14, 10,false, false); // AckCTSLng = 14 use 1M bps send ++ ++ // Figure out time required to transmit this frame. ++ ThisFrameTime = ComputeTxTime(len + sCrcLng, ++ rtl8180_rate2rate(rate), ++ false, ++ bUseShortPreamble); ++ ++ // RTS-CTS-ThisFrame-ACK. ++ RtsDur = CtsTime + ThisFrameTime + AckTime + 3*aSifsTime; ++ ++ TxDescDuration = RtsTime + RtsDur; ++ }else {// Normal case. ++ bCTSEnable = false; ++ bRTSEnable = false; ++ RtsDur = 0; ++ ++ ThisFrameTime = ComputeTxTime(len + sCrcLng, rtl8180_rate2rate(rate), false, bUseShortPreamble); ++ TxDescDuration = ThisFrameTime + aSifsTime + AckTime; ++ } ++ ++ if(!(frag_hdr->frame_ctl & IEEE80211_FCTL_MOREFRAGS)) { //no more fragment ++ // ThisFrame-ACK. ++ Duration = aSifsTime + AckTime; ++ } else { // One or more fragments remained. ++ u16 NextFragTime; ++ NextFragTime = ComputeTxTime( len + sCrcLng, //pretend following packet length equal current packet ++ rtl8180_rate2rate(rate), ++ false, bUseShortPreamble ); ++ ++ //ThisFrag-ACk-NextFrag-ACK. ++ Duration = NextFragTime + 3*aSifsTime + 2*AckTime; ++ } ++ ++ } // End of Unicast packet ++ ++ ++ //fill the tx desriptor ++ tx[0] |= len & 0xfff; ++#ifdef JOHN_HWSEC ++ if(frag_hdr->frame_ctl & IEEE80211_FCTL_WEP ){ ++ tx[0] &= 0xffff7fff; ++ //group key may be different from pairwise key ++ if( frag_hdr->addr1[0]==0xff && ++ frag_hdr->addr1[0]==0xff && ++ frag_hdr->addr1[0]==0xff && ++ frag_hdr->addr1[0]==0xff && ++ frag_hdr->addr1[0]==0xff && ++ frag_hdr->addr1[0]==0xff ){ ++ if(ieee->broadcast_key_type == KEY_TYPE_CCMP) tx[7] |= 0x2;//ccmp ++ else tx[7] |= 0x1;//wep and tkip ++ } ++ else { ++ if(ieee->pairwise_key_type == KEY_TYPE_CCMP) tx[7] |= 0x2;//CCMP ++ else tx[7] |= 0x1;//WEP and TKIP ++ } ++ } ++ else ++#endif /*JOHN_HWSEC*/ ++ ++ tx[0] |= (1<<15); ++ ++ if (priv->ieee80211->current_network.capability&WLAN_CAPABILITY_SHORT_PREAMBLE){ ++ if (priv->plcp_preamble_mode==1 && rate!=0) { // short mode now, not long! ++ tx[0] |= (1<<16); ++ } // enable short preamble mode. ++ } ++ ++ if(morefrag) tx[0] |= (1<<17); ++ //printk(KERN_WARNING "rtl_rate = %d\n", rate); ++ tx[0] |= (rate << 24); //TX rate ++ frag_hdr->duration_id = Duration; ++ ++ if(NIC_8187B == priv->card_8187) { ++ if(bCTSEnable) { ++ tx[0] |= (1<<18); ++ } ++ ++ if(bRTSEnable) //rts enable ++ { ++ tx[0] |= ((ieeerate2rtlrate(priv->ieee80211->basic_rate))<<19);//RTS RATE ++ tx[0] |= (1<<23);//rts enable ++ tx[1] |= RtsDur;//RTS Duration ++ } ++ tx[3] |= (TxDescDuration<<16); //DURATION ++ if( WLAN_FC_GET_STYPE(le16_to_cpu(frag_hdr->frame_ctl)) == IEEE80211_STYPE_PROBE_RESP ) ++ tx[5] |= (1<<8);//(priv->retry_data<<8); //retry lim ; ++ else ++ tx[5] |= (11<<8);//(priv->retry_data<<8); //retry lim ; ++ ++ //frag_hdr->duration_id = Duration; ++ memcpy(tx+8,txbuf,len); ++ } else { ++ if ( (len>priv->rts) && priv->rts && priority==LOW_PRIORITY){ ++ tx[0] |= (1<<23); //enalbe RTS function ++ tx[1] |= RtsDur; //Need to edit here! ----hikaru ++ } ++ else { ++ tx[1]=0; ++ } ++ tx[0] |= (ieeerate2rtlrate(priv->ieee80211->basic_rate) << 19); /* RTS RATE - should be basic rate */ ++ ++ tx[2] = 3; // CW min ++ tx[2] |= (7<<4); //CW max ++ tx[2] |= (11<<8);//(priv->retry_data<<8); //retry lim ++ ++ // printk("%x\n%x\n",tx[0],tx[1]); ++ ++#ifdef DUMP_TX ++ int i; ++ printk("--rate %x---",rate); ++ for (i = 0; i < (len + 3); i++) ++ printk("%2x", ((u8*)tx)[i]); ++ printk("---------------\n"); ++#endif ++ memcpy(tx+3,txbuf,len); ++ } ++ ++#ifdef JOHN_DUMP_TXDESC ++ int i; ++ printk("--rate %x---",rate); ++ for (i = 0; i < 8; i++) ++ printk("%8x ", tx[i]); ++ printk("\n"); ++#endif ++#ifdef JOHN_DUMP_TXPKT ++ { ++ int j; ++ printk("\n---------------------------------------------------------------------\n"); ++ printk("--rate %x--urb_len in decimal %d",rate, urb_len); ++ for (j = 32; j < (urb_len); j++){ ++ if( ( (j-32)%24 )==0 ) printk("\n"); ++ printk("%2x ", ((u8*)tx)[j]); ++ } ++ printk("\n---------------------------------------------------------------------\n"); ++ ++ } ++#endif ++ ++ if(NIC_8187 == priv->card_8187) { ++ usb_fill_bulk_urb(tx_urb,priv->udev, ++ usb_sndbulkpipe(priv->udev,priority), tx, ++ urb_len, (priority == LOW_PRIORITY)?rtl8187_lptx_isr:rtl8187_nptx_isr, dev); ++ ++ } else { ++ //printk(KERN_WARNING "Tx packet use by submit urb!\n"); ++ /* FIXME check what EP is for low/norm PRI */ ++ usb_fill_bulk_urb(tx_urb,priv->udev, ++ usb_sndbulkpipe(priv->udev,priority), tx, ++ urb_len, TXISR_SELECT(priority), dev); ++ } ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ status = usb_submit_urb(tx_urb, GFP_ATOMIC); ++#else ++ status = usb_submit_urb(tx_urb); ++#endif ++ ++ if (!status){ ++ //atomic_inc((priority == NORM_PRIORITY)? &priv->tx_np_pending : &priv->tx_lp_pending); ++ atomic_inc(&priv->tx_pending[priority]); ++ dev->trans_start = jiffies; ++ //printk("=====> tx_pending[%d]=%d\n", priority, atomic_read(&priv->tx_pending[priority])); ++ return 0; ++ }else{ ++ DMESGE("Error TX URB %d, error pending %d", ++ //atomic_read((priority == NORM_PRIORITY)? &priv->tx_np_pending : &priv->tx_lp_pending), ++ atomic_read(&priv->tx_pending[priority]), ++ status); ++ return -1; ++ } ++} ++ ++ short rtl8187_usb_initendpoints(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ priv->rx_urb = (struct urb**) kmalloc (sizeof(struct urb*) * (MAX_RX_URB+1), GFP_KERNEL); ++ ++ memset(priv->rx_urb, 0, sizeof(struct urb*) * MAX_RX_URB); ++ ++#ifdef JACKSON_NEW_RX ++ priv->pp_rxskb = (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) * MAX_RX_URB, GFP_KERNEL); ++ if (priv->pp_rxskb == NULL) ++ goto destroy; ++ ++ memset(priv->pp_rxskb, 0, sizeof(struct sk_buff*) * MAX_RX_URB); ++#endif ++#ifdef THOMAS_BEACON ++ { ++ int align; ++ unsigned long oldaddr,newaddr; //lzm mod for 64bit cpu crash 20081107 ++ priv->rx_urb[MAX_RX_URB] = usb_alloc_urb(0, GFP_KERNEL); ++ priv->oldaddr = kmalloc(16, GFP_KERNEL); ++ oldaddr = (unsigned long)priv->oldaddr; ++ align = oldaddr&3; ++ if(align != 0 ){ ++ newaddr = oldaddr + 4 - align; ++ priv->rx_urb[MAX_RX_URB]->transfer_buffer_length = 16-4+align; ++ } ++ else{ ++ newaddr = oldaddr; ++ priv->rx_urb[MAX_RX_URB]->transfer_buffer_length = 16; ++ } ++ priv->rx_urb[MAX_RX_URB]->transfer_buffer = (u32*)newaddr; ++ } ++#endif ++ ++ ++ goto _middle; ++ ++ ++destroy: ++ ++#ifdef JACKSON_NEW_RX ++ if (priv->pp_rxskb) { ++ kfree(priv->pp_rxskb); ++ priv->pp_rxskb = NULL; ++ ++ } ++#endif ++ if (priv->rx_urb) { ++ kfree(priv->rx_urb); ++ } ++ priv->rx_urb = NULL; ++ ++ DMESGE("Endpoint Alloc Failure"); ++ return -ENOMEM; ++ ++ ++_middle: ++ ++ return 0; ++ ++} ++#ifdef THOMAS_BEACON ++void rtl8187_usb_deleteendpoints(struct net_device *dev) ++{ ++ int i; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if( in_interrupt() ) ++ printk(KERN_ALERT " %ld in interrupt \n",in_interrupt() ); ++ if(priv->rx_urb){ ++ for(i=0;i<(MAX_RX_URB+1);i++){ ++ if(priv->rx_urb[i]) { ++ usb_kill_urb(priv->rx_urb[i]); ++ usb_free_urb(priv->rx_urb[i]); ++ } ++ } ++ kfree(priv->rx_urb); ++ priv->rx_urb = NULL; ++ } ++ if(priv->oldaddr){ ++ kfree(priv->oldaddr); ++ priv->oldaddr = NULL; ++ } ++ if (priv->pp_rxskb) { ++ kfree(priv->pp_rxskb); ++ priv->pp_rxskb = 0; ++ } ++} ++#endif ++ ++void rtl8187_set_rate(struct net_device *dev) ++{ ++ int i; ++ u16 word; ++ int basic_rate,min_rr_rate,max_rr_rate; ++ ++ //if (ieee80211_is_54g(priv->ieee80211->current_network) && ++ // priv->ieee80211->state == IEEE80211_LINKED){ ++ basic_rate = ieeerate2rtlrate(240); ++ min_rr_rate = ieeerate2rtlrate(60); ++ max_rr_rate = ieeerate2rtlrate(240); ++ ++ /* ++ }else{ ++ basic_rate = ieeerate2rtlrate(20); ++ min_rr_rate = ieeerate2rtlrate(10); ++ max_rr_rate = ieeerate2rtlrate(110); ++ } ++ */ ++ ++ write_nic_byte(dev, RESP_RATE, ++ max_rr_rate<beacon_interval); ++ rtl8187_net_update(dev); ++ /*update timing params*/ ++ rtl8180_set_chan(dev, priv->chan); ++ rtl8187_set_rxconf(dev); ++} ++ ++#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20) ++void rtl8180_wmm_param_update(struct work_struct* work) ++{ ++ struct ieee80211_device * ieee = container_of(work, struct ieee80211_device,wmm_param_update_wq); ++ struct net_device *dev = ieee->dev; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++#else ++void rtl8180_wmm_param_update(struct ieee80211_device *ieee) ++{ ++ struct net_device *dev = ieee->dev; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++#endif ++ u8 *ac_param = (u8 *)(ieee->current_network.wmm_param); ++ u8 mode = ieee->current_network.mode; ++ AC_CODING eACI; ++ AC_PARAM AcParam; ++ PAC_PARAM pAcParam; ++ u8 i; ++ ++ //8187 need not to update wmm param, added by David, 2006.9.8 ++ if(NIC_8187 == priv->card_8187) { ++ return; ++ } ++ ++ if(!ieee->current_network.QoS_Enable) ++ { ++ //legacy ac_xx_param update ++ ++ AcParam.longData = 0; ++ AcParam.f.AciAifsn.f.AIFSN = 2; // Follow 802.11 DIFS. ++ AcParam.f.AciAifsn.f.ACM = 0; ++ AcParam.f.Ecw.f.ECWmin = 3; // Follow 802.11 CWmin. ++ AcParam.f.Ecw.f.ECWmax = 7; // Follow 802.11 CWmax. ++ AcParam.f.TXOPLimit = 0; ++ for(eACI = 0; eACI < AC_MAX; eACI++) ++ { ++ AcParam.f.AciAifsn.f.ACI = (u8)eACI; ++ { ++ u8 u1bAIFS; ++ u32 u4bAcParam; ++ ++ ++ pAcParam = (PAC_PARAM)(&AcParam); ++ // Retrive paramters to udpate. ++ u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN *(((mode&IEEE_G) == IEEE_G)?9:20) + aSifsTime; ++ u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit)) << AC_PARAM_TXOP_LIMIT_OFFSET) | ++ (((u32)(pAcParam->f.Ecw.f.ECWmax)) << AC_PARAM_ECW_MAX_OFFSET) | ++ (((u32)(pAcParam->f.Ecw.f.ECWmin)) << AC_PARAM_ECW_MIN_OFFSET) | ++ (((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET)); ++ ++ switch(eACI) ++ { ++ case AC1_BK: ++ write_nic_dword(dev, AC_BK_PARAM, u4bAcParam); ++ break; ++ ++ case AC0_BE: ++ write_nic_dword(dev, AC_BE_PARAM, u4bAcParam); ++ break; ++ ++ case AC2_VI: ++ write_nic_dword(dev, AC_VI_PARAM, u4bAcParam); ++ break; ++ ++ case AC3_VO: ++ write_nic_dword(dev, AC_VO_PARAM, u4bAcParam); ++ break; ++ ++ default: ++ printk(KERN_WARNING "SetHwReg8185(): invalid ACI: %d !\n", eACI); ++ break; ++ } ++ } ++ } ++ ++ return; ++ } ++ // ++ for(i = 0; i < AC_MAX; i++){ ++ pAcParam = (AC_PARAM * )ac_param; ++ { ++ AC_CODING eACI; ++ u8 u1bAIFS; ++ u32 u4bAcParam; ++ ++ // Retrive paramters to udpate. ++ eACI = pAcParam->f.AciAifsn.f.ACI; ++ //Mode G/A: slotTimeTimer = 9; Mode B: 20 ++ u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * (((mode&IEEE_G) == IEEE_G)?9:20) + aSifsTime; ++ u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit)) << AC_PARAM_TXOP_LIMIT_OFFSET) | ++ (((u32)(pAcParam->f.Ecw.f.ECWmax)) << AC_PARAM_ECW_MAX_OFFSET) | ++ (((u32)(pAcParam->f.Ecw.f.ECWmin)) << AC_PARAM_ECW_MIN_OFFSET) | ++ (((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET)); ++ ++ switch(eACI) ++ { ++ case AC1_BK: ++ write_nic_dword(dev, AC_BK_PARAM, u4bAcParam); ++ //printk(KERN_WARNING "[%04x]:0x%08x\n",AC_BK_PARAM,read_nic_dword(dev, AC_BK_PARAM)); ++ break; ++ ++ case AC0_BE: ++ write_nic_dword(dev, AC_BE_PARAM, u4bAcParam); ++ //printk(KERN_WARNING "[%04x]:0x%08x\n",AC_BE_PARAM,read_nic_dword(dev, AC_BE_PARAM)); ++ break; ++ ++ case AC2_VI: ++ write_nic_dword(dev, AC_VI_PARAM, u4bAcParam); ++ //printk(KERN_WARNING "[%04x]:0x%08x\n",AC_VI_PARAM,read_nic_dword(dev, AC_VI_PARAM)); ++ break; ++ ++ case AC3_VO: ++ write_nic_dword(dev, AC_VO_PARAM, u4bAcParam); ++ //printk(KERN_WARNING "[%04x]:0x%08x\n",AC_VO_PARAM,read_nic_dword(dev, AC_VO_PARAM)); ++ break; ++ ++ default: ++ printk(KERN_WARNING "SetHwReg8185(): invalid ACI: %d !\n", eACI); ++ break; ++ } ++ } ++ ac_param += (sizeof(AC_PARAM)); ++ } ++} ++ ++int IncludedInSupportedRates(struct r8180_priv *priv, u8 TxRate ) ++{ ++ u8 rate_len; ++ u8 rate_ex_len; ++ u8 RateMask = 0x7F; ++ u8 idx; ++ unsigned short Found = 0; ++ u8 NaiveTxRate = TxRate&RateMask; ++ ++ rate_len = priv->ieee80211->current_network.rates_len; ++ rate_ex_len = priv->ieee80211->current_network.rates_ex_len; ++ ++ for( idx=0; idx< rate_len; idx++ ){ ++ if( (priv->ieee80211->current_network.rates[idx] & RateMask) == NaiveTxRate ) { ++ Found = 1; ++ goto found_rate; ++ } ++ } ++ ++ for( idx=0; idx< rate_ex_len; idx++ ) { ++ if( (priv->ieee80211->current_network.rates_ex[idx] & RateMask) == NaiveTxRate ) { ++ Found = 1; ++ goto found_rate; ++ } ++ } ++ ++ return Found; ++ found_rate: ++ return Found; ++} ++// ++// Description: ++// Get the Tx rate one degree up form the input rate in the supported rates. ++// Return the upgrade rate if it is successed, otherwise return the input rate. ++// By Bruce, 2007-06-05. ++// ++u8 GetUpgradeTxRate(struct net_device *dev, u8 rate) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u8 UpRate; ++ ++ // Upgrade 1 degree. ++ switch(rate) ++ { ++ case 108: // Up to 54Mbps. ++ UpRate = 108; ++ break; ++ ++ case 96: // Up to 54Mbps. ++ UpRate = 108; ++ break; ++ ++ case 72: // Up to 48Mbps. ++ UpRate = 96; ++ break; ++ ++ case 48: // Up to 36Mbps. ++ UpRate = 72; ++ break; ++ ++ case 36: // Up to 24Mbps. ++ UpRate = 48; ++ break; ++ ++ case 22: // Up to 18Mbps. ++ UpRate = 36; ++ break; ++ ++ case 11: // Up to 11Mbps. ++ UpRate = 22; ++ break; ++ ++ case 4: // Up to 5.5Mbps. ++ UpRate = 11; ++ break; ++ ++ case 2: // Up to 2Mbps. ++ UpRate = 4; ++ break; ++ ++ default: ++ printk("GetUpgradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate); ++ return rate; ++ } ++ // Check if the rate is valid. ++ if(IncludedInSupportedRates(priv, UpRate)) ++ { ++// printk("GetUpgradeTxRate(): GetUpgrade Tx rate(%d) from %d !\n", UpRate, priv->CurrentOperaRate); ++ return UpRate; ++ } ++ else ++ { ++ printk("GetUpgradeTxRate(): Tx rate (%d) is not in supported rates\n", UpRate); ++ return rate; ++ } ++ return rate; ++} ++// ++// Description: ++// Get the Tx rate one degree down form the input rate in the supported rates. ++// Return the degrade rate if it is successed, otherwise return the input rate. ++// By Bruce, 2007-06-05. ++// ++u8 GetDegradeTxRate( struct net_device *dev, u8 rate) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u8 DownRate; ++ ++ // Upgrade 1 degree. ++ switch(rate) ++ { ++ case 108: // Down to 48Mbps. ++ DownRate = 96; ++ break; ++ ++ case 96: // Down to 36Mbps. ++ DownRate = 72; ++ break; ++ ++ case 72: // Down to 24Mbps. ++ DownRate = 48; ++ break; ++ ++ case 48: // Down to 18Mbps. ++ DownRate = 36; ++ break; ++ ++ case 36: // Down to 11Mbps. ++ DownRate = 22; ++ break; ++ ++ case 22: // Down to 5.5Mbps. ++ DownRate = 11; ++ break; ++ ++ case 11: // Down to 2Mbps. ++ DownRate = 4; ++ break; ++ ++ case 4: // Down to 1Mbps. ++ DownRate = 2; ++ break; ++ ++ case 2: // Down to 1Mbps. ++ DownRate = 2; ++ break; ++ ++ default: ++ printk("GetDegradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate); ++ return rate; ++ } ++ // Check if the rate is valid. ++ if(IncludedInSupportedRates(priv, DownRate)){ ++// printk("GetDegradeTxRate(): GetDegrade Tx rate(%d) from %d!\n", DownRate, priv->CurrentOperaRate); ++ return DownRate; ++ }else{ ++ printk("GetDegradeTxRate(): Tx rate (%d) is not in supported rates\n", DownRate); ++ return rate; ++ } ++ return rate; ++} ++ ++// ++// Helper function to determine if specified data rate is ++// CCK rate. ++// 2005.01.25, by rcnjko. ++// ++bool MgntIsCckRate(u16 rate ) ++{ ++ bool bReturn = false; ++ ++ if((rate <= 22) && (rate != 12) && (rate != 18)){ ++ bReturn = true; ++ } ++ ++ return bReturn; ++} ++//by amy for rate adaptive ++// ++// Description: ++// Core logic to adjust Tx data rate in STA mode according to ++// OFDM retry count ratio. ++// ++// Note: ++// RTL8187 : pHalData->CurrRetryCnt = TallyCnt ++// RTL8187B : pHalData->CurrRetryCnt = PktRetryCnt in TxClosedCommand ++// ++void sta_rateadaptive8187B(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ unsigned long CurrTxokCnt; ++ u16 CurrRetryCnt; ++ u16 CurrRetryRate; ++ unsigned long CurrRxokCnt; ++ bool bTryUp = false; ++ bool bTryDown = false; ++ u8 TryUpTh = 1; ++ u8 TryDownTh = 2; ++ u32 TxThroughput; ++ long CurrSignalStrength; ++ bool bUpdateInitialGain = false; ++ CurrRetryCnt = priv->CurrRetryCnt; ++ CurrTxokCnt = (priv->stats.txbeaconokint + priv->stats.txmanageokint + ++ priv->stats.txvookint + priv->stats.txviokint + priv->stats.txbeokint)- priv->LastTxokCnt; ++ CurrRxokCnt = priv->stats.rxok - priv->LastRxokCnt; ++ CurrSignalStrength = priv->RecvSignalPower; ++ TxThroughput = (u32)(priv->txokbytestotal - priv->LastTxOKBytes); ++ priv->LastTxOKBytes = priv->txokbytestotal; ++ priv->CurrentOperaRate = priv->ieee80211->rate / 5; ++ //printk("priv->CurrentOperaRate is %d\n",priv->CurrentOperaRate); ++ ++#if 1 ++ //2 Compute retry ratio. ++ if (CurrTxokCnt>0) ++ { ++ CurrRetryRate = (u16)(CurrRetryCnt*100/CurrTxokCnt); ++ } ++ else ++ { // It may be serious retry. To distinguish serious retry or no packets modified by Bruce ++ CurrRetryRate = (u16)(CurrRetryCnt*100/1); ++ } ++#endif ++ ++ ++ //printk("\n(1) priv->LastRetryRate: %d \n",priv->LastRetryRate); ++ //printk("(2) CurrRetryCnt = %d \n", CurrRetryCnt); ++ //printk("(3) TxokCnt = %d \n", CurrTxokCnt); ++ //printk("(4) CurrRetryRate = %d \n", CurrRetryRate); ++ //printk("(5) SignalStrength = %d \n",priv->RecvSignalPower); ++ ++ priv->LastRetryCnt = priv->CurrRetryCnt; ++ priv->LastTxokCnt = (priv->stats.txbeaconokint + priv->stats.txmanageokint + ++ priv->stats.txvookint + priv->stats.txviokint + priv->stats.txbeokint); ++ priv->LastRxokCnt = priv->stats.rxok; ++ priv->CurrRetryCnt = 0; ++ //2No Tx packets, return to init_rate or not? ++ if (CurrRetryRate==0 && CurrTxokCnt == 0) ++ { ++ // ++ // 2007.04.09, by Roger. after 4.5 seconds in this condition, we try to raise rate. ++ // ++ priv->TryupingCountNoData++; ++ ++ //printk("No Tx packets, TryupingCountNoData(%d)\n", priv->TryupingCountNoData); ++ //printk("(6) priv->CurrentOperaRate =%d\n", priv->CurrentOperaRate); ++ ++ if (priv->TryupingCountNoData>15) ++ { ++ priv->TryupingCountNoData = 0; ++ priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate); ++ // Reset Fail Record ++ priv->LastFailTxRate = 0; ++ priv->LastFailTxRateSS = -200; ++ priv->FailTxRateCount = 0; ++ } ++ goto SetInitialGain; ++ } ++ else ++ { ++ priv->TryupingCountNoData=0; //Reset trying up times. ++ } ++ ++ // ++ // For Netgear case, I comment out the following signal strength estimation, ++ // which can results in lower rate to transmit when sample is NOT enough (e.g. PING request). ++ // 2007.04.09, by Roger. ++ // ++#if 1 ++ // If sample is not enough, we use signalstrength. ++ if ( CurrTxokCnt<10|| CurrRetryCnt<10) ++ { ++ //printk("Sample is not enough, we use signalstrength for rate adaptive\n"); ++ //After 3 sec, and trying up. ++ priv->TryupingCountNoData++; ++ if (priv->TryupingCountNoData>10) ++ { ++ //printk("Sample is not enough and After 3 sec try up\n"); ++ priv->TryupingCountNoData=0; ++ ++ // ++ // Added by Roger, 2007.01.04. ++ // Signal strength plus 3 for air link. ++ // ++ ++ if ( CurrSignalStrength>-68 )//&& IncludedInSupportedRates(Adapter, 108) ) ++ { ++ priv->ieee80211->rate = 540; ++ //pMgntInfo->CurrentOperaRate = 108; ++ } ++ else if (CurrSignalStrength>-70)// && IncludedInSupportedRates(Adapter, 96) ) ++ { ++ priv->ieee80211->rate = 480; ++ //pMgntInfo->CurrentOperaRate = 96; ++ } ++ else if (CurrSignalStrength>-73)// && IncludedInSupportedRates(Adapter, 72) ) ++ { ++ priv->ieee80211->rate = 360; ++ //pMgntInfo->CurrentOperaRate = 72; ++ } ++ else if (CurrSignalStrength>-79)// && IncludedInSupportedRates(Adapter, 48) ) ++ { ++ priv->ieee80211->rate = 240; ++ //pMgntInfo->CurrentOperaRate = 48; ++ } ++ else if (CurrSignalStrength>-81)// && IncludedInSupportedRates(Adapter, 36) ) ++ { ++ priv->ieee80211->rate = 180; ++ //pMgntInfo->CurrentOperaRate = 36; ++ } ++ else if (CurrSignalStrength>-83)// && IncludedInSupportedRates(Adapter, 22) ) ++ { ++ priv->ieee80211->rate = 110; ++ //pMgntInfo->CurrentOperaRate = 22; ++ } ++ else if (CurrSignalStrength>-85)// && IncludedInSupportedRates(Adapter, 11) ) ++ { ++ priv->ieee80211->rate = 55; ++ //pMgntInfo->CurrentOperaRate = 11; ++ } ++ else if (CurrSignalStrength>-89)// && IncludedInSupportedRates(Adapter, 4) ) ++ { ++ priv->ieee80211->rate = 20; ++ //pMgntInfo->CurrentOperaRate = 4; ++ } ++ ++ ++ } ++ ++ //2004.12.23 skip record for 0 ++ //pHalData->LastRetryRate = CurrRetryRate; ++ //printk("pMgntInfo->CurrentOperaRate =%d\n",priv->ieee80211->rate); ++ return; ++ } ++ else ++ { ++ priv->TryupingCountNoData=0; ++ } ++#endif ++ // ++ // Restructure rate adaptive as the following main stages: ++ // (1) Add retry threshold in 54M upgrading condition with signal strength. ++ // (2) Add the mechanism to degrade to CCK rate according to signal strength ++ // and retry rate. ++ // (3) Remove all Initial Gain Updates over OFDM rate. To avoid the complicated ++ // situation, Initial Gain Update is upon on DIG mechanism except CCK rate. ++ // (4) Add the mehanism of trying to upgrade tx rate. ++ // (5) Record the information of upping tx rate to avoid trying upping tx rate constantly. ++ // By Bruce, 2007-06-05. ++ // ++ // ++ ++ // 11Mbps or 36Mbps ++ // Check more times in these rate(key rates). ++ // ++ if(priv->CurrentOperaRate == 22 || priv->CurrentOperaRate == 72) ++ { ++ TryUpTh += 9; ++ } ++ // ++ // Let these rates down more difficult. ++ // ++ if(MgntIsCckRate(priv->CurrentOperaRate) || priv->CurrentOperaRate == 36) ++ { ++ TryDownTh += 1; ++ } ++ ++ //1 Adjust Rate. ++ if (priv->bTryuping == true) ++ { ++ //2 For Test Upgrading mechanism ++ // Note: ++ // Sometimes the throughput is upon on the capability bwtween the AP and NIC, ++ // thus the low data rate does not improve the performance. ++ // We randomly upgrade the data rate and check if the retry rate is improved. ++ ++ // Upgrading rate did not improve the retry rate, fallback to the original rate. ++ if ( (CurrRetryRate > 25) && TxThroughput < priv->LastTxThroughput) ++ { ++ //Not necessary raising rate, fall back rate. ++ bTryDown = true; ++ //printk("Not necessary raising rate, fall back rate....\n"); ++ //printk("(7) priv->CurrentOperaRate =%d, TxThroughput = %d, LastThroughput = %d\n", ++ // priv->CurrentOperaRate, TxThroughput, priv->LastTxThroughput); ++ } ++ else ++ { ++ priv->bTryuping = false; ++ } ++ } ++ else if (CurrSignalStrength > -51 && (CurrRetryRate < 100)) ++ { ++ //2For High Power ++ // ++ // Added by Roger, 2007.04.09. ++ // Return to highest data rate, if signal strength is good enough. ++ // SignalStrength threshold(-50dbm) is for RTL8186. ++ // Revise SignalStrength threshold to -51dbm. ++ // ++ // Also need to check retry rate for safety, by Bruce, 2007-06-05. ++ if(priv->CurrentOperaRate != 108) ++ { ++ bTryUp = true; ++ // Upgrade Tx Rate directly. ++ priv->TryupingCount += TryUpTh; ++ //printk("StaRateAdaptive87B: Power(%d) is high enough!!. \n", CurrSignalStrength); ++ } ++ } ++ // To avoid unstable rate jumping, comment out this condition, by Bruce, 2007-06-26. ++ /* ++ else if(CurrSignalStrength < -86 && CurrRetryRate >= 100) ++ { ++ //2 For Low Power ++ // ++ // Low signal strength and high current tx rate may cause Tx rate to degrade too slowly. ++ // Update Tx rate to CCK rate directly. ++ // By Bruce, 2007-06-05. ++ // ++ if(!MgntIsCckRate(pMgntInfo->CurrentOperaRate)) ++ { ++ if(CurrSignalStrength > -88 && IncludedInSupportedRates(Adapter, 22)) // 11M ++ pMgntInfo->CurrentOperaRate = 22; ++ else if(CurrSignalStrength > -90 && IncludedInSupportedRates(Adapter, 11)) // 5.5M ++ pMgntInfo->CurrentOperaRate = 11; ++ else if(CurrSignalStrength > -92 && IncludedInSupportedRates(Adapter, 4)) // 2M ++ pMgntInfo->CurrentOperaRate = 4; ++ else // 1M ++ pMgntInfo->CurrentOperaRate = 2; ++ } ++ else if(CurrRetryRate >= 200) ++ { ++ pMgntInfo->CurrentOperaRate = GetDegradeTxRate(Adapter, pMgntInfo->CurrentOperaRate); ++ } ++ RT_TRACE(COMP_RATE, DBG_LOUD, ("RA: Low Power(%d), or High Retry Rate(%d), set rate to CCK rate (%d). \n", ++ CurrSignalStrength, CurrRetryRate, pMgntInfo->CurrentOperaRate)); ++ bUpdateInitialGain = TRUE; ++ // Reset Fail Record ++ pHalData->LastFailTxRate = 0; ++ pHalData->LastFailTxRateSS = -200; ++ pHalData->FailTxRateCount = 0; ++ goto SetInitialGain; ++ } ++ */ ++ else if(CurrTxokCnt< 100 && CurrRetryRate >= 600) ++ { ++ //2 For Serious Retry ++ // ++ // Traffic is not busy but our Tx retry is serious. ++ // ++ bTryDown = true; ++ // Let Rate Mechanism to degrade tx rate directly. ++ priv->TryDownCountLowData += TryDownTh; ++ //printk("RA: Tx Retry is serious. Degrade Tx Rate to %d directly...\n", priv->CurrentOperaRate); ++ } ++ else if ( priv->CurrentOperaRate == 108 ) ++ { ++ //2For 54Mbps ++ // if ( (CurrRetryRate>38)&&(pHalData->LastRetryRate>35)) ++ if ( (CurrRetryRate>33)&&(priv->LastRetryRate>32)) ++ { ++ //(30,25) for cable link threshold. (38,35) for air link. ++ //Down to rate 48Mbps. ++ bTryDown = true; ++ } ++ } ++ else if ( priv->CurrentOperaRate == 96 ) ++ { ++ //2For 48Mbps ++ // if ( ((CurrRetryRate>73) && (pHalData->LastRetryRate>72)) && IncludedInSupportedRates(Adapter, 72) ) ++ if ( ((CurrRetryRate>48) && (priv->LastRetryRate>47))) ++ { ++ //(73, 72) for temp used. ++ //(25, 23) for cable link, (60,59) for air link. ++ //CurrRetryRate plus 25 and 26 respectively for air link. ++ //Down to rate 36Mbps. ++ bTryDown = true; ++ } ++ else if ( (CurrRetryRate<8) && (priv->LastRetryRate<8) ) //TO DO: need to consider (RSSI) ++ { ++ bTryUp = true; ++ } ++ } ++ else if ( priv->CurrentOperaRate == 72 ) ++ { ++ //2For 36Mbps ++ //if ( (CurrRetryRate>97) && (pHalData->LastRetryRate>97)) ++ if ( (CurrRetryRate>55) && (priv->LastRetryRate>54)) ++ { ++ //(30,25) for cable link threshold respectively. (103,10) for air link respectively. ++ //CurrRetryRate plus 65 and 69 respectively for air link threshold. ++ //Down to rate 24Mbps. ++ bTryDown = true; ++ } ++ // else if ( (CurrRetryRate<20) && (pHalData->LastRetryRate<20) && IncludedInSupportedRates(Adapter, 96) )//&& (device->LastRetryRate<15) ) //TO DO: need to consider (RSSI) ++ else if ( (CurrRetryRate<15) && (priv->LastRetryRate<16))//&& (device->LastRetryRate<15) ) //TO DO: need to consider (RSSI) ++ { ++ bTryUp = true; ++ } ++ } ++ else if ( priv->CurrentOperaRate == 48 ) ++ { ++ //2For 24Mbps ++ // if ( ((CurrRetryRate>119) && (pHalData->LastRetryRate>119) && IncludedInSupportedRates(Adapter, 36))) ++ if ( ((CurrRetryRate>63) && (priv->LastRetryRate>62))) ++ { ++ //(15,15) for cable link threshold respectively. (119, 119) for air link threshold. ++ //Plus 84 for air link threshold. ++ //Down to rate 18Mbps. ++ bTryDown = true; ++ } ++ // else if ( (CurrRetryRate<14) && (pHalData->LastRetryRate<15) && IncludedInSupportedRates(Adapter, 72)) //TO DO: need to consider (RSSI) ++ else if ( (CurrRetryRate<20) && (priv->LastRetryRate<21)) //TO DO: need to consider (RSSI) ++ { ++ bTryUp = true; ++ } ++ } ++ else if ( priv->CurrentOperaRate == 36 ) ++ { ++ //2For 18Mbps ++ if ( ((CurrRetryRate>109) && (priv->LastRetryRate>109))) ++ { ++ //(99,99) for cable link, (109,109) for air link. ++ //Down to rate 11Mbps. ++ bTryDown = true; ++ } ++ // else if ( (CurrRetryRate<15) && (pHalData->LastRetryRate<16) && IncludedInSupportedRates(Adapter, 48)) //TO DO: need to consider (RSSI) ++ else if ( (CurrRetryRate<25) && (priv->LastRetryRate<26)) //TO DO: need to consider (RSSI) ++ { ++ bTryUp = true; ++ } ++ } ++ else if ( priv->CurrentOperaRate == 22 ) ++ { ++ //2For 11Mbps ++ // if (CurrRetryRate>299 && IncludedInSupportedRates(Adapter, 11)) ++ if (CurrRetryRate>95) ++ { ++ bTryDown = true; ++ } ++ else if (CurrRetryRate<55)//&& (device->LastRetryRate<55) ) //TO DO: need to consider (RSSI) ++ { ++ bTryUp = true; ++ } ++ } ++ else if ( priv->CurrentOperaRate == 11 ) ++ { ++ //2For 5.5Mbps ++ // if (CurrRetryRate>159 && IncludedInSupportedRates(Adapter, 4) ) ++ if (CurrRetryRate>149) ++ { ++ bTryDown = true; ++ } ++ // else if ( (CurrRetryRate<30) && (pHalData->LastRetryRate<30) && IncludedInSupportedRates(Adapter, 22) ) ++ else if ( (CurrRetryRate<60) && (priv->LastRetryRate < 65)) ++ { ++ bTryUp = true; ++ } ++ } ++ else if ( priv->CurrentOperaRate == 4 ) ++ { ++ //2For 2 Mbps ++ if((CurrRetryRate>99) && (priv->LastRetryRate>99)) ++ { ++ bTryDown = true; ++ } ++ // else if ( (CurrRetryRate<50) && (pHalData->LastRetryRate<65) && IncludedInSupportedRates(Adapter, 11) ) ++ else if ( (CurrRetryRate < 65) && (priv->LastRetryRate < 70)) ++ { ++ bTryUp = true; ++ } ++ } ++ else if ( priv->CurrentOperaRate == 2 ) ++ { ++ //2For 1 Mbps ++ // if ( (CurrRetryRate<50) && (pHalData->LastRetryRate<65) && IncludedInSupportedRates(Adapter, 4)) ++ if ( (CurrRetryRate<70) && (priv->LastRetryRate<75)) ++ { ++ bTryUp = true; ++ } ++ } ++ if(bTryUp && bTryDown) ++ printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n"); ++ ++ //1 Test Upgrading Tx Rate ++ // Sometimes the cause of the low throughput (high retry rate) is the compatibility between the AP and NIC. ++ // To test if the upper rate may cause lower retry rate, this mechanism randomly occurs to test upgrading tx rate. ++ if(!bTryUp && !bTryDown && (priv->TryupingCount == 0) && (priv->TryDownCountLowData == 0) ++ && priv->CurrentOperaRate != 108 && priv->FailTxRateCount < 2) ++ { ++#if 1 ++ if(jiffies% (CurrRetryRate + 101) == 0) ++ { ++ bTryUp = true; ++ priv->bTryuping = true; ++ printk("======================================================>StaRateAdaptive87B(): Randomly try upgrading...\n"); ++ } ++#endif ++ } ++ //1 Rate Mechanism ++ if(bTryUp) ++ { ++ priv->TryupingCount++; ++ priv->TryDownCountLowData = 0; ++ ++ // ++ // Check more times if we need to upgrade indeed. ++ // Because the largest value of pHalData->TryupingCount is 0xFFFF and ++ // the largest value of pHalData->FailTxRateCount is 0x14, ++ // this condition will be satisfied at most every 2 min. ++ // ++ if((priv->TryupingCount > (TryUpTh + priv->FailTxRateCount * priv->FailTxRateCount)) || ++ (CurrSignalStrength > priv->LastFailTxRateSS) || priv->bTryuping) ++ { ++ priv->TryupingCount = 0; ++ // ++ // When transfering from CCK to OFDM, DIG is an important issue. ++ // ++ if(priv->CurrentOperaRate == 22) ++ bUpdateInitialGain = true; ++ // (1)To avoid upgrade frequently to the fail tx rate, add the FailTxRateCount into the threshold. ++ // (2)If the signal strength is increased, it may be able to upgrade. ++ priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate); ++ //printk("StaRateAdaptive87B(): Upgrade Tx Rate to %d\n", priv->CurrentOperaRate); ++ ++ // Update Fail Tx rate and count. ++ if(priv->LastFailTxRate != priv->CurrentOperaRate) ++ { ++ priv->LastFailTxRate = priv->CurrentOperaRate; ++ priv->FailTxRateCount = 0; ++ priv->LastFailTxRateSS = -200; // Set lowest power. ++ } ++ } ++ } ++ else ++ { ++ if(priv->TryupingCount > 0) ++ priv->TryupingCount --; ++ } ++ ++ if(bTryDown) ++ { ++ priv->TryDownCountLowData++; ++ priv->TryupingCount = 0; ++ ++ ++ //Check if Tx rate can be degraded or Test trying upgrading should fallback. ++ if(priv->TryDownCountLowData > TryDownTh || priv->bTryuping) ++ { ++ priv->TryDownCountLowData = 0; ++ priv->bTryuping = false; ++ // Update fail information. ++ if(priv->LastFailTxRate == priv->CurrentOperaRate) ++ { ++ priv->FailTxRateCount ++; ++ // Record the Tx fail rate signal strength. ++ if(CurrSignalStrength > priv->LastFailTxRateSS) ++ { ++ priv->LastFailTxRateSS = CurrSignalStrength; ++ } ++ } ++ else ++ { ++ priv->LastFailTxRate = priv->CurrentOperaRate; ++ priv->FailTxRateCount = 1; ++ priv->LastFailTxRateSS = CurrSignalStrength; ++ } ++ priv->CurrentOperaRate = GetDegradeTxRate(dev, priv->CurrentOperaRate); ++ // ++ // When it is CCK rate, it may need to update initial gain to receive lower power packets. ++ // ++ if(MgntIsCckRate(priv->CurrentOperaRate)) ++ { ++ bUpdateInitialGain = true; ++ } ++ //printk("StaRateAdaptive87B(): Degrade Tx Rate to %d\n", priv->CurrentOperaRate); ++ } ++ } ++ else ++ { ++ if(priv->TryDownCountLowData > 0) ++ priv->TryDownCountLowData --; ++ } ++ // Keep the Tx fail rate count to equal to 0x15 at most. ++ // Reduce the fail count at least to 10 sec if tx rate is tending stable. ++ if(priv->FailTxRateCount >= 0x15 || ++ (!bTryUp && !bTryDown && priv->TryDownCountLowData == 0 && priv->TryupingCount && priv->FailTxRateCount > 0x6)) ++ { ++ priv->FailTxRateCount --; ++ } ++ ++ // ++ // We need update initial gain when we set tx rate "from OFDM to CCK" or ++ // "from CCK to OFDM". ++ // ++SetInitialGain: ++#if 1 //to be done ++ if(bUpdateInitialGain) ++ { ++ if(MgntIsCckRate(priv->CurrentOperaRate)) // CCK ++ { ++ if(priv->InitialGain > priv->RegBModeGainStage) ++ { ++ if(CurrSignalStrength < -85) // Low power, OFDM [0x17] = 26. ++ { ++ priv->InitialGain = priv->RegBModeGainStage; ++ } ++ else if(priv->InitialGain > priv->RegBModeGainStage + 1) ++ { ++ priv->InitialGain -= 2; ++ } ++ else ++ { ++ priv->InitialGain --; ++ } ++ UpdateInitialGain(dev); ++ } ++ } ++ else // OFDM ++ { ++ if(priv->InitialGain < 4) ++ { ++ priv->InitialGain ++; ++ UpdateInitialGain(dev); ++ } ++ } ++ } ++#endif ++ //Record the related info ++ priv->LastRetryRate = CurrRetryRate; ++ priv->LastTxThroughput = TxThroughput; ++ priv->ieee80211->rate = priv->CurrentOperaRate * 5; ++} ++ ++#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20) ++void rtl8180_rate_adapter(struct work_struct * work) ++{ ++ struct delayed_work *dwork = container_of(work,struct delayed_work,work); ++ struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,rate_adapter_wq); ++ struct net_device *dev = ieee->dev; ++#else ++void rtl8180_rate_adapter(struct net_device *dev) ++{ ++ ++#endif ++ sta_rateadaptive8187B(dev); ++} ++ ++void timer_rate_adaptive(unsigned long data) ++{ ++ struct r8180_priv* priv = ieee80211_priv((struct net_device *)data); ++ //DMESG("---->timer_rate_adaptive()\n"); ++ if(!priv->up) ++ { ++ //DMESG("<----timer_rate_adaptive():driver is not up!\n"); ++ return; ++ } ++ if( (priv->ieee80211->mode != IEEE_B) && ++ (priv->ieee80211->iw_mode != IW_MODE_MASTER) ++ && ((priv->ieee80211->state == IEEE80211_LINKED)||(priv->ieee80211->state == IEEE80211_MESH_LINKED))) ++ { ++ //DMESG("timer_rate_adaptive():schedule rate_adapter_wq\n"); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++ queue_delayed_work(priv->ieee80211->wq,&priv->ieee80211->rate_adapter_wq, 0); ++#else ++ queue_work(priv->ieee80211->wq,&priv->ieee80211->rate_adapter_wq); ++#endif ++ } ++ ++ mod_timer(&priv->rateadapter_timer, jiffies + MSECS(DEFAULT_RATE_ADAPTIVE_TIMER_PERIOD)); ++ //DMESG("<----timer_rate_adaptive()\n"); ++} ++//by amy for rate adaptive ++ ++ ++void rtl8180_irq_rx_tasklet_new(struct r8180_priv *priv); ++void rtl8180_irq_rx_tasklet(struct r8180_priv *priv); ++ ++//YJ,add,080828,for KeepAlive ++#if 0 ++static void MgntLinkKeepAlive(struct r8180_priv *priv ) ++{ ++ if (priv->keepAliveLevel == 0) ++ return; ++ ++ if(priv->ieee80211->state == IEEE80211_LINKED) ++ { ++ // ++ // Keep-Alive. ++ // ++ //printk("LastTx:%d Tx:%d LastRx:%d Rx:%ld Idle:%d\n",priv->link_detect.LastNumTxUnicast,priv->NumTxUnicast, priv->link_detect.LastNumRxUnicast, priv->ieee80211->NumRxUnicast, priv->link_detect.IdleCount); ++ ++ if ( (priv->keepAliveLevel== 2) || ++ (priv->link_detect.LastNumTxUnicast == priv->NumTxUnicast && ++ priv->link_detect.LastNumRxUnicast == priv->ieee80211->NumRxUnicast ) ++ ) ++ { ++ priv->link_detect.IdleCount++; ++ ++ // ++ // Send a Keep-Alive packet packet to AP if we had been idle for a while. ++ // ++ if(priv->link_detect.IdleCount >= ((KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD)-1) ) ++ { ++ priv->link_detect.IdleCount = 0; ++ ieee80211_sta_ps_send_null_frame(priv->ieee80211, false); ++ } ++ } ++ else ++ { ++ priv->link_detect.IdleCount = 0; ++ } ++ priv->link_detect.LastNumTxUnicast = priv->NumTxUnicast; ++ priv->link_detect.LastNumRxUnicast = priv->ieee80211->NumRxUnicast; ++ } ++} ++//YJ,add,080828,for KeepAlive,end ++#endif ++void InactivePowerSave(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ ++ // ++ // This flag "bSwRfProcessing", indicates the status of IPS procedure, should be set if the IPS workitem ++ // is really scheduled. ++ // The old code, sets this flag before scheduling the IPS workitem and however, at the same time the ++ // previous IPS workitem did not end yet, fails to schedule the current workitem. Thus, bSwRfProcessing ++ // blocks the IPS procedure of switching RF. ++ // By Bruce, 2007-12-25. ++ // ++ priv->bSwRfProcessing = true; ++ MgntActSet_RF_State(dev, priv->eInactivePowerState, RF_CHANGE_BY_IPS); ++ ++ // ++ // To solve CAM values miss in RF OFF, rewrite CAM values after RF ON. By Bruce, 2007-09-20. ++ // ++#if 0 ++ while( index < 4 ) ++ { ++ if( ( pMgntInfo->SecurityInfo.PairwiseEncAlgorithm == WEP104_Encryption ) || ++ (pMgntInfo->SecurityInfo.PairwiseEncAlgorithm == WEP40_Encryption) ) ++ { ++ if( pMgntInfo->SecurityInfo.KeyLen[index] != 0) ++ pAdapter->HalFunc.SetKeyHandler(pAdapter, index, 0, FALSE, pMgntInfo->SecurityInfo.PairwiseEncAlgorithm, TRUE, FALSE); ++ ++ } ++ index++; ++ } ++#endif ++ priv->bSwRfProcessing = false; ++} ++ ++// ++// Description: ++// Enter the inactive power save mode. RF will be off ++// 2007.08.17, by shien chang. ++// ++void IPSEnter(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ RT_RF_POWER_STATE rtState; ++ ++ if (priv->bInactivePs) ++ { ++ rtState = priv->eRFPowerState; ++ ++ // ++ // Added by Bruce, 2007-12-25. ++ // Do not enter IPS in the following conditions: ++ // (1) RF is already OFF or Sleep ++ // (2) bSwRfProcessing (indicates the IPS is still under going) ++ // (3) Connectted (only disconnected can trigger IPS) ++ // (4) IBSS (send Beacon) ++ // (5) AP mode (send Beacon) ++ // ++ if (rtState == eRfOn && !priv->bSwRfProcessing && (priv->ieee80211->iw_mode != IW_MODE_ADHOC) ++ && (priv->ieee80211->state != IEEE80211_LINKED )) ++ { ++#ifdef CONFIG_RADIO_DEBUG ++ DMESG("IPSEnter(): Turn off RF."); ++#endif ++ priv->eInactivePowerState = eRfOff; ++ InactivePowerSave(dev); ++ //SetRFPowerState(dev, priv->eInactivePowerState); ++ //MgntActSet_RF_State(dev, priv->eInactivePowerState, RF_CHANGE_BY_IPS); ++ } ++ } ++ //printk("priv->eRFPowerState is %d\n",priv->eRFPowerState); ++} ++ ++void IPSLeave(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ RT_RF_POWER_STATE rtState; ++ if (priv->bInactivePs) ++ { ++ rtState = priv->eRFPowerState; ++ if (rtState == eRfOff && (!priv->bSwRfProcessing) && priv->RfOffReason <= RF_CHANGE_BY_IPS) ++ { ++#ifdef CONFIG_RADIO_DEBUG ++ DMESG("ISLeave(): Turn on RF."); ++#endif ++ priv->eInactivePowerState = eRfOn; ++ InactivePowerSave(dev); ++ } ++ } ++// printk("priv->eRFPowerState is %d\n",priv->eRFPowerState); ++} ++//by amy for power save ++ ++//YJ,add,081230 ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void IPSLeave_wq (struct work_struct *work) ++{ ++ struct ieee80211_device *ieee = container_of(work,struct ieee80211_device,ips_leave_wq); ++ struct net_device *dev = ieee->dev; ++#else ++void IPSLeave_wq(struct net_device *dev) ++{ ++#endif ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ down(&priv->ieee80211->ips_sem); ++ IPSLeave(dev); ++ up(&priv->ieee80211->ips_sem); ++} ++ ++void ieee80211_ips_leave(struct net_device *dev) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ if(priv->bInactivePs){ ++ if(priv->eRFPowerState == eRfOff) ++ { ++ //DMESG("%s", __FUNCTION__); ++ queue_work(priv->ieee80211->wq,&priv->ieee80211->ips_leave_wq); ++ } ++ } ++} ++//YJ,add,081230,end ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void rtl8180_watch_dog_wq (struct work_struct *work) ++{ ++ struct delayed_work *dwork = container_of(work,struct delayed_work,work); ++ struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,watch_dog_wq); ++ struct net_device *dev = ieee->dev; ++#else ++void rtl8180_watch_dog_wq(struct net_device *dev) ++{ ++#endif ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ //bool bEnterPS = false; ++ //bool bBusyTraffic = false; ++ u32 TotalRxNum = 0; ++ u16 SlotIndex = 0, i=0; ++ //YJ,add,080828,for link state check ++ if((priv->ieee80211->state == IEEE80211_LINKED) && (priv->ieee80211->iw_mode == IW_MODE_INFRA)){ ++ SlotIndex = (priv->link_detect.SlotIndex++) % priv->link_detect.SlotNum; ++ priv->link_detect.RxFrameNum[SlotIndex] = priv->ieee80211->NumRxDataInPeriod + priv->ieee80211->NumRxBcnInPeriod; ++ for( i=0; ilink_detect.SlotNum; i++ ) ++ TotalRxNum+= priv->link_detect.RxFrameNum[i]; ++#if 0 //for roaming temp del ++ if(TotalRxNum == 0){ ++ priv->ieee80211->state = IEEE80211_ASSOCIATING; ++ printk("=========>turn to another AP\n"); ++ queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq); ++ } ++#endif ++ } ++ priv->link_detect.NumRxOkInPeriod = 0; ++ priv->link_detect.NumTxOkInPeriod = 0; ++ priv->ieee80211->NumRxDataInPeriod = 0; ++ priv->ieee80211->NumRxBcnInPeriod = 0; ++ ++#ifdef CONFIG_IPS ++ if(priv->ieee80211->actscanning == false){ ++ if((priv->ieee80211->iw_mode == IW_MODE_INFRA) && ++ (priv->ieee80211->state == IEEE80211_NOLINK) && ++ (priv->eRFPowerState == eRfOn)) ++ { ++ //printk("actscanning:%d, state:%d, eRFPowerState:%d\n", ++ // priv->ieee80211->actscanning, ++ // priv->ieee80211->state, ++ // priv->eRFPowerState); ++ ++ down(&priv->ieee80211->ips_sem); ++ IPSEnter(dev); ++ up(&priv->ieee80211->ips_sem); ++ } ++ } ++ //queue_delayed_work(priv->ieee80211->wq,&priv->ieee80211->watch_dog_wq,IEEE80211_WATCH_DOG_TIME); ++#endif ++ ++ //printk("========================>leave rtl8180_watch_dog_wq()\n"); ++} ++ ++void watch_dog_adaptive(unsigned long data) ++{ ++ struct net_device* dev = (struct net_device*)data; ++ struct r8180_priv* priv = ieee80211_priv(dev); ++ //DMESG("---->watch_dog_adaptive()\n"); ++ if(!priv->up){ ++ //DMESG("<----watch_dog_adaptive():driver is not up!\n"); ++ return; ++ } ++ // Tx and Rx High Power Mechanism. ++ if(CheckHighPower(dev)){ ++ //printk("===============================> high power!\n"); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++ queue_delayed_work(priv->ieee80211->wq,&priv->ieee80211->tx_pw_wq, 0); ++#else ++ queue_work(priv->ieee80211->wq,&priv->ieee80211->tx_pw_wq); ++#endif ++ } ++ ++ // Schedule an workitem to perform DIG ++ if(CheckDig(dev) == true){ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++ queue_delayed_work(priv->ieee80211->wq,&priv->ieee80211->hw_dig_wq,0); ++#else ++ queue_work(priv->ieee80211->wq,&priv->ieee80211->hw_dig_wq); ++#endif ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++ queue_delayed_work(priv->ieee80211->wq,&priv->ieee80211->watch_dog_wq,0); ++#else ++ queue_work(priv->ieee80211->wq,&priv->ieee80211->watch_dog_wq); ++#endif ++ ++ mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME)); ++ //DMESG("<----watch_dog_adaptive()\n"); ++} ++ ++#ifdef ENABLE_DOT11D ++ ++CHANNEL_LIST Current_tbl; ++ ++static CHANNEL_LIST ChannelPlan[] = { ++ {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64},19}, //FCC ++ {{1,2,3,4,5,6,7,8,9,10,11},11}, //IC ++ {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //ETSI ++ {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //Spain. Change to ETSI. ++ {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //France. Change to ETSI. ++ {{14,36,40,44,48,52,56,60,64},9}, //MKK ++ {{1,2,3,4,5,6,7,8,9,10,11,12,13,14, 36,40,44,48,52,56,60,64},22},//MKK1 ++ {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //Israel. ++ {{1,2,3,4,5,6,7,8,9,10,11,12,13,34,38,42,46},17}, // For 11a , TELEC ++ {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14}, //For Global Domain. 1-11:active scan, 12-14 passive scan. //+YJ, 080626 ++ {{1,2,3,4,5,6,7,8,9,10,11,12,13},13} //world wide 13: ch1~ch11 active scan, ch12~13 passive //lzm add 081205 ++}; ++ ++static void rtl8180_set_channel_map(u8 channel_plan, struct ieee80211_device *ieee) ++{ ++ int i; ++ ++ //lzm add 081205 ++ ieee->MinPassiveChnlNum=MAX_CHANNEL_NUMBER+1; ++ ieee->IbssStartChnl=0; ++ ++ switch (channel_plan) ++ { ++ case COUNTRY_CODE_FCC: ++ case COUNTRY_CODE_IC: ++ case COUNTRY_CODE_ETSI: ++ case COUNTRY_CODE_SPAIN: ++ case COUNTRY_CODE_FRANCE: ++ case COUNTRY_CODE_MKK: ++ case COUNTRY_CODE_MKK1: ++ case COUNTRY_CODE_ISRAEL: ++ case COUNTRY_CODE_TELEC: ++ { ++ Dot11d_Init(ieee); ++ ieee->bGlobalDomain = false; ++ ieee->bWorldWide13 = false; ++ if (ChannelPlan[channel_plan].Len != 0){ ++ // Clear old channel map ++ memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map)); ++ // Set new channel map ++ for (i=0;ichannel_map[ChannelPlan[channel_plan].Channel[i]] = 1; ++ } ++ } ++ break; ++ } ++ case COUNTRY_CODE_GLOBAL_DOMAIN: ++ { ++ GET_DOT11D_INFO(ieee)->bEnabled = 0; ++ Dot11d_Reset(ieee); ++ ieee->bGlobalDomain = true; ++ ieee->bWorldWide13 = false; ++ ++ //lzm add 081205 ++ ieee->MinPassiveChnlNum=12; ++ ieee->IbssStartChnl= 10; ++ ++ break; ++ } ++ case COUNTRY_CODE_WORLD_WIDE_13_INDEX://lzm add 081205 ++ { ++ Dot11d_Init(ieee); ++ ieee->bGlobalDomain = false; ++ ieee->bWorldWide13 = true; ++ ++ //lzm add 081205 ++ ieee->MinPassiveChnlNum=12; ++ ieee->IbssStartChnl= 10; ++ ++ if (ChannelPlan[channel_plan].Len != 0){ ++ // Clear old channel map ++ memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map)); ++ // Set new channel map ++ for (i=0;ichannel_map[ChannelPlan[channel_plan].Channel[i]] = 1; ++ else//ch12~13 passive scan ++ GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 2; ++ } ++ } ++ ++ break; ++ } ++ default: ++ { ++ Dot11d_Init(ieee); ++ ieee->bGlobalDomain = false; ++ ieee->bWorldWide13 = false; ++ memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map)); ++ for (i=1;i<=14;i++) ++ { ++ GET_DOT11D_INFO(ieee)->channel_map[i] = 1; ++ } ++ break; ++ } ++ } ++} ++#endif ++ ++ ++//Add for RF power on power off by lizhaoming 080512 ++#ifdef POLLING_METHOD_FOR_RADIO ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void GPIOChangeRFWorkItemCallBack(struct work_struct *work); ++#else ++void GPIOChangeRFWorkItemCallBack(struct ieee80211_device *ieee); ++#endif ++void gpio_change_polling(unsigned long data); ++#endif ++ ++ ++static void rtl8180_link_detect_init(plink_detect_t plink_detect) ++{ ++ memset(plink_detect, 0, sizeof(link_detect_t)); ++ plink_detect->SlotNum = DEFAULT_SLOT_NUM; ++} ++ ++#ifdef SW_ANTE_DIVERSITY ++static void rtl8187_antenna_diversity_read(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u16 usValue; ++ ++ //2 Read CustomerID ++ usValue = eprom_read(dev, EEPROM_SW_REVD_OFFSET>>1); ++ priv->EEPROMCustomerID = (u8)( usValue & EEPROM_CID_MASK ); ++ //DMESG("EEPROM Customer ID: %02X\n", priv->EEPROMCustomerID); ++ ++ //2 Read AntennaDiversity ++ // SW Antenna Diversity. ++ if( (usValue & EEPROM_SW_AD_MASK) != EEPROM_SW_AD_ENABLE ){ ++ priv->EEPROMSwAntennaDiversity = false; ++ DMESG("EEPROM Disable SW Antenna Diversity"); ++ }else{ ++ priv->EEPROMSwAntennaDiversity = true; ++ DMESG("EEPROM Enable SW Antenna Diversity"); ++ } ++ // Default Antenna to use. ++ if( (usValue & EEPROM_DEF_ANT_MASK) != EEPROM_DEF_ANT_1 ) { ++ priv->EEPROMDefaultAntenna1 = false; ++ DMESG("EEPROM Default Main Antenna 0"); ++ }else{ ++ priv->EEPROMDefaultAntenna1 = false; ++ DMESG( "EEPROM Default Aux Antenna 1"); ++ } ++ ++ // ++ // Antenna diversity mechanism. Added by Roger, 2007.11.05. ++ // ++ if( priv->RegSwAntennaDiversityMechanism == 0 ) // Auto //set it to 0 when init ++ {// 0: default from EEPROM. ++ priv->bSwAntennaDiverity = priv->EEPROMSwAntennaDiversity; ++ }else{// 1:disable antenna diversity, 2: enable antenna diversity. ++ priv->bSwAntennaDiverity = ((priv->RegSwAntennaDiversityMechanism == 1)? false : true); ++ } ++ //DMESG("bSwAntennaDiverity = %d\n", priv->bSwAntennaDiverity); ++ ++ ++ // ++ // Default antenna settings. Added by Roger, 2007.11.05. ++ // ++ if( priv->RegDefaultAntenna == 0)//set it to 0 when init ++ { // 0: default from EEPROM. ++ priv->bDefaultAntenna1 = priv->EEPROMDefaultAntenna1; ++ }else{// 1: main, 2: aux. ++ priv->bDefaultAntenna1 = ((priv->RegDefaultAntenna== 2) ? true : false); ++ } ++ //DMESG("bDefaultAntenna1 = %d\n", priv->bDefaultAntenna1); ++ ++//by amy for antenna ++} ++#endif ++ ++short rtl8180_init(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int i, j; ++ u16 word; ++ //int ch; ++ //u16 version; ++ u8 hw_version; ++ //u8 config3; ++ struct usb_device *udev; ++ u16 idProduct; ++ u16 bcdDevice; ++ //u8 chan_plan_index; ++ ++ //FIXME: these constants are placed in a bad pleace. ++ ++ //priv->txbuffsize = 1024; ++ //priv->txringcount = 32; ++ //priv->rxbuffersize = 1024; ++ //priv->rxringcount = 32; ++ //priv->txbeaconcount = 3; ++ //priv->rx_skb_complete = 1; ++ //priv->txnp_pending.ispending=0; ++ /* ^^ the SKB does not containt a partial RXed packet (is empty) */ ++ ++ //memcpy(priv->stats,0,sizeof(struct Stats)); ++ ++ //priv->irq_enabled=0; ++ priv->driver_upping = 0; ++ priv->commit = 0; ++ ++ //priv->stats.rxdmafail=0; ++ priv->stats.txrdu=0; ++ //priv->stats.rxrdu=0; ++ //priv->stats.rxnolast=0; ++ //priv->stats.rxnodata=0; ++ //priv->stats.rxreset=0; ++ //priv->stats.rxwrkaround=0; ++ //priv->stats.rxnopointer=0; ++ priv->stats.txbeerr=0; ++ priv->stats.txbkerr=0; ++ priv->stats.txvierr=0; ++ priv->stats.txvoerr=0; ++ priv->stats.txmanageerr=0; ++ priv->stats.txbeaconerr=0; ++ priv->stats.txresumed=0; ++ //priv->stats.rxerr=0; ++ //priv->stats.rxoverflow=0; ++ //priv->stats.rxint=0; ++ priv->stats.txbeokint=0; ++ priv->stats.txbkokint=0; ++ priv->stats.txviokint=0; ++ priv->stats.txvookint=0; ++ priv->stats.txmanageokint=0; ++ priv->stats.txbeaconokint=0; ++ /*priv->stats.txhpokint=0; ++ priv->stats.txhperr=0;*/ ++ priv->stats.rxurberr=0; ++ priv->stats.rxstaterr=0; ++ priv->stats.txoverflow=0; ++ priv->stats.rxok=0; ++ //priv->stats.txbeaconerr=0; ++ //priv->stats.txlperr=0; ++ //priv->stats.txlpokint=0; ++//john ++ priv->stats.txnpdrop=0; ++ priv->stats.txlpdrop =0; ++ priv->stats.txbedrop =0; ++ priv->stats.txbkdrop =0; ++ priv->stats.txvidrop =0; ++ priv->stats.txvodrop =0; ++ priv->stats.txbeacondrop =0; ++ priv->stats.txmanagedrop =0; ++ ++ // priv->stats.txokbytestotal =0; ++//by amy ++ priv->LastSignalStrengthInPercent=0; ++ priv->SignalStrength=0; ++ priv->SignalQuality=0; ++ priv->antenna_flag=0; ++ priv->flag_beacon = false; ++//by amy ++//david ++ //radion on defaultly ++ priv->radion = 1; ++//david ++//by amy for rate adaptive ++ priv->CurrRetryCnt=0; ++ priv->LastRetryCnt=0; ++ priv->LastTxokCnt=0; ++ priv->LastRxokCnt=0; ++ priv->LastRetryRate=0; ++ priv->bTryuping=0; ++ priv->CurrTxRate=0; ++ priv->CurrRetryRate=0; ++ priv->TryupingCount=0; ++ priv->TryupingCountNoData=0; ++ priv->TryDownCountLowData=0; ++ priv->RecvSignalPower=0; ++ priv->LastTxOKBytes=0; ++ priv->LastFailTxRate=0; ++ priv->LastFailTxRateSS=0; ++ priv->FailTxRateCount=0; ++ priv->LastTxThroughput=0; ++ priv->txokbytestotal=0; ++//by amy for rate adaptive ++//by amy for ps ++ priv->RFChangeInProgress = false; ++ priv->SetRFPowerStateInProgress = false; ++ priv->RFProgType = 0; ++ priv->bInHctTest = false; ++ priv->bInactivePs = true;//false; ++ priv->ieee80211->bInactivePs = priv->bInactivePs; ++ priv->eInactivePowerState = eRfOn;//lzm add for IPS and Polling methord ++ priv->bSwRfProcessing = false; ++ priv->eRFPowerState = eRfOff; ++ priv->RfOffReason = 0; ++ priv->NumRxOkInPeriod = 0; ++ priv->NumTxOkInPeriod = 0; ++ priv->bLeisurePs = true; ++ priv->dot11PowerSaveMode = eActive; ++ priv->RegThreeWireMode=HW_THREE_WIRE_BY_8051; ++ priv->ps_mode = false; ++//by amy for ps ++//by amy for DIG ++ priv->bDigMechanism = 1; ++ priv->bCCKThMechanism = 0; ++ priv->InitialGain = 0; ++ priv->StageCCKTh = 0; ++ priv->RegBModeGainStage = 2; ++//by amy for DIG ++// {by david for DIG, 2008.3.6 ++ priv->RegDigOfdmFaUpTh = 0x0c; ++ priv->RegBModeGainStage = 0x02; ++ priv->DIG_NumberFallbackVote = 0; ++ priv->DIG_NumberUpgradeVote = 0; ++ priv->CCKUpperTh = 0x100; ++ priv->CCKLowerTh = 0x20; ++//} ++//{added by david for High tx power, 2008.3.11 ++ priv->bRegHighPowerMechanism = true; ++ priv->bToUpdateTxPwr = false; ++ ++ priv->Z2HiPwrUpperTh = 77; ++ priv->Z2HiPwrLowerTh = 75; ++ priv->Z2RSSIHiPwrUpperTh = 70; ++ priv->Z2RSSIHiPwrLowerTh = 20; ++ //specify for rtl8187B ++ priv->wMacRegRfPinsOutput = 0x0480; ++ priv->wMacRegRfPinsSelect = 0x2488; ++ // ++ // Note that, we just set TrSwState to TR_HW_CONTROLLED here instead of changing ++ // HW setting because we assume it should be inialized as HW controlled. 061010, by rcnjko. ++ // ++ priv->TrSwitchState = TR_HW_CONTROLLED; ++//} ++ priv->ieee80211->iw_mode = IW_MODE_INFRA; ++//test pending bug, john 20070815 ++ for(i=0;i<0x10;i++) atomic_set(&(priv->tx_pending[i]), 0); ++//by lizhaoming ++#ifdef POLLING_METHOD_FOR_RADIO ++ priv->wlan_first_up_flag1 = 0; ++ priv->polling_timer_on = 0;//add for S3/S4 ++#endif ++//by lizhaoming for LED ++#ifdef LED ++ priv->ieee80211->ieee80211_led_contorl = LedControl8187; ++#endif ++#ifdef CONFIG_IPS ++ priv->ieee80211->ieee80211_ips_leave = ieee80211_ips_leave;//IPSLeave; ++#endif ++ ++#ifdef SW_ANTE_DIVERSITY ++ priv->antb=0; ++ priv->diversity=1; ++ priv->LastRxPktAntenna = 0; ++ priv->AdMinCheckPeriod = 5; ++ priv->AdMaxCheckPeriod = 10; ++ // Lower signal strength threshold to fit the HW participation in antenna diversity. +by amy 080312 ++ priv->AdMaxRxSsThreshold = 30;//60->30 ++ priv->AdRxSsThreshold = 20;//50->20 ++ priv->AdCheckPeriod = priv->AdMinCheckPeriod; ++ priv->AdTickCount = 0; ++ priv->AdRxSignalStrength = -1; ++ priv->RegSwAntennaDiversityMechanism = 0; ++ priv->RegDefaultAntenna = 0; ++ priv->SignalStrength = 0; ++ priv->AdRxOkCnt = 0; ++ priv->CurrAntennaIndex = 0; ++ priv->AdRxSsBeforeSwitched = 0; ++ init_timer(&priv->SwAntennaDiversityTimer); ++ priv->SwAntennaDiversityTimer.data = (unsigned long)dev; ++ priv->SwAntennaDiversityTimer.function = (void *)SwAntennaDiversityTimerCallback; ++#endif ++ ++ priv->retry_rts = DEFAULT_RETRY_RTS; ++ priv->retry_data = DEFAULT_RETRY_DATA; ++ priv->ieee80211->rate = 110; //11 mbps ++ priv->CurrentOperaRate=priv->ieee80211->rate/5; ++ priv->ieee80211->short_slot = 1; ++ priv->ieee80211->mode = IEEE_G; ++ priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0; ++ ++ rtl8180_link_detect_init(&priv->link_detect); ++ ++ spin_lock_init(&priv->tx_lock); ++ spin_lock_init(&priv->irq_lock);//added by thomas ++ spin_lock_init(&priv->rf_ps_lock); ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++ INIT_WORK(&priv->reset_wq, (void*)rtl8180_restart); ++ INIT_WORK(&priv->ieee80211->ips_leave_wq, (void*)IPSLeave_wq); //YJ,add,081230,for IPS ++ INIT_DELAYED_WORK(&priv->ieee80211->rate_adapter_wq,(void*)rtl8180_rate_adapter); ++ INIT_DELAYED_WORK(&priv->ieee80211->hw_dig_wq,(void*)rtl8180_hw_dig_wq); ++ INIT_DELAYED_WORK(&priv->ieee80211->watch_dog_wq,(void*)rtl8180_watch_dog_wq); ++ INIT_DELAYED_WORK(&priv->ieee80211->tx_pw_wq,(void*)rtl8180_tx_pw_wq); ++ ++//add for RF power on power off by lizhaoming 080512 ++#ifdef POLLING_METHOD_FOR_RADIO ++ INIT_DELAYED_WORK(&priv->ieee80211->GPIOChangeRFWorkItem, (void*)GPIOChangeRFWorkItemCallBack); ++#endif ++ ++#ifdef SW_ANTE_DIVERSITY ++ INIT_DELAYED_WORK(&priv->ieee80211->SwAntennaWorkItem,(void*) SwAntennaWorkItemCallback); ++#endif ++ ++#else ++ INIT_WORK(&priv->reset_wq,(void*) rtl8180_restart,dev); ++ INIT_WORK(&priv->ieee80211->ips_leave_wq, (void*)IPSLeave_wq,dev); //YJ,add,081230,for IPS ++ INIT_WORK(&priv->ieee80211->rate_adapter_wq,(void*)rtl8180_rate_adapter,dev); ++ INIT_WORK(&priv->ieee80211->hw_dig_wq,(void*)rtl8180_hw_dig_wq,dev); ++ INIT_WORK(&priv->ieee80211->watch_dog_wq,(void*)rtl8180_watch_dog_wq,dev); ++ INIT_WORK(&priv->ieee80211->tx_pw_wq,(void*)rtl8180_tx_pw_wq,dev); ++ ++//add for RF power on power off by lizhaoming 080512 ++#ifdef POLLING_METHOD_FOR_RADIO ++ INIT_WORK(&priv->ieee80211->GPIOChangeRFWorkItem,(void*) GPIOChangeRFWorkItemCallBack, priv->ieee80211); ++#endif ++ ++#ifdef SW_ANTE_DIVERSITY ++ INIT_WORK(&priv->ieee80211->SwAntennaWorkItem,(void*) SwAntennaWorkItemCallback, dev); ++#endif ++ ++#endif ++#else ++ tq_init(&priv->reset_wq,(void*) rtl8180_restart,dev); ++#endif ++ sema_init(&priv->wx_sem,1); ++ sema_init(&priv->set_chan_sem,1); ++#ifdef THOMAS_TASKLET ++ tasklet_init(&priv->irq_rx_tasklet, ++ (void(*)(unsigned long))rtl8180_irq_rx_tasklet_new, ++ (unsigned long)priv); ++#else ++ tasklet_init(&priv->irq_rx_tasklet, ++ (void(*)(unsigned long))rtl8180_irq_rx_tasklet, ++ (unsigned long)priv); ++#endif ++//by lizhaoming for Radio on/off ++#ifdef POLLING_METHOD_FOR_RADIO ++ init_timer(&priv->gpio_polling_timer); ++ priv->gpio_polling_timer.data = (unsigned long)dev; ++ priv->gpio_polling_timer.function = gpio_change_polling; ++#endif ++//by amy for rate adaptive ++ init_timer(&priv->rateadapter_timer); ++ priv->rateadapter_timer.data = (unsigned long)dev; ++ priv->rateadapter_timer.function = timer_rate_adaptive; ++//by amy for rate adaptive ++//by amy for ps ++ init_timer(&priv->watch_dog_timer); ++ priv->watch_dog_timer.data = (unsigned long)dev; ++ priv->watch_dog_timer.function = watch_dog_adaptive; ++//by amy ++//by amy for ps ++ priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL; ++ priv->ieee80211->iw_mode = IW_MODE_INFRA; ++ priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN | ++ IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ | ++#ifdef CONFIG_SOFT_BEACON ++ IEEE_SOFTMAC_BEACONS | //IEEE_SOFTMAC_SINGLE_QUEUE; ++#endif ++ IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE; ++ ++ priv->ieee80211->active_scan = 1; ++ //priv->ieee80211->ch_lock = 0; ++ priv->ieee80211->rate = 110; //11 mbps ++ priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION; ++ priv->ieee80211->host_encrypt = 1; ++ priv->ieee80211->host_decrypt = 1; ++#ifdef CONFIG_SOFT_BEACON ++ priv->ieee80211->start_send_beacons = NULL; ++ priv->ieee80211->stop_send_beacons = NULL; ++#else ++ priv->ieee80211->start_send_beacons = rtl8187_beacon_tx; ++ priv->ieee80211->stop_send_beacons = rtl8187_beacon_stop; ++#endif ++ priv->ieee80211->softmac_hard_start_xmit = rtl8180_hard_start_xmit; ++ priv->ieee80211->set_chan = rtl8180_set_chan; ++ priv->ieee80211->link_change = rtl8187_link_change; ++ priv->ieee80211->softmac_data_hard_start_xmit = rtl8180_hard_data_xmit; ++ priv->ieee80211->data_hard_stop = rtl8180_data_hard_stop; ++ priv->ieee80211->data_hard_resume = rtl8180_data_hard_resume; ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ priv->ieee80211->meshScanMode = 0; ++ priv->mshobj = alloc_mshobj(priv); ++ if(priv->mshobj) ++ { ++ priv->ieee80211->ext_patch_ieee80211_start_protocol = priv->mshobj->ext_patch_ieee80211_start_protocol; ++ priv->ieee80211->ext_patch_ieee80211_stop_protocol = priv->mshobj->ext_patch_ieee80211_stop_protocol; ++//by amy for mesh ++ priv->ieee80211->ext_patch_ieee80211_start_mesh = priv->mshobj->ext_patch_ieee80211_start_mesh; ++//by amy for mesh ++ priv->ieee80211->ext_patch_ieee80211_probe_req_1 = priv->mshobj->ext_patch_ieee80211_probe_req_1; ++ priv->ieee80211->ext_patch_ieee80211_probe_req_2 = priv->mshobj->ext_patch_ieee80211_probe_req_2; ++ priv->ieee80211->ext_patch_ieee80211_association_req_1 = priv->mshobj->ext_patch_ieee80211_association_req_1; ++ priv->ieee80211->ext_patch_ieee80211_association_req_2 = priv->mshobj->ext_patch_ieee80211_association_req_2; ++ priv->ieee80211->ext_patch_ieee80211_assoc_resp_by_net_1 = priv->mshobj->ext_patch_ieee80211_assoc_resp_by_net_1; ++ priv->ieee80211->ext_patch_ieee80211_assoc_resp_by_net_2 = priv->mshobj->ext_patch_ieee80211_assoc_resp_by_net_2; ++ priv->ieee80211->ext_patch_ieee80211_rx_frame_softmac_on_auth = priv->mshobj->ext_patch_ieee80211_rx_frame_softmac_on_auth; ++ priv->ieee80211->ext_patch_ieee80211_rx_frame_softmac_on_deauth = priv->mshobj->ext_patch_ieee80211_rx_frame_softmac_on_deauth; ++ priv->ieee80211->ext_patch_ieee80211_rx_frame_softmac_on_assoc_req = priv->mshobj->ext_patch_ieee80211_rx_frame_softmac_on_assoc_req; ++ priv->ieee80211->ext_patch_ieee80211_rx_frame_softmac_on_assoc_rsp = priv->mshobj->ext_patch_ieee80211_rx_frame_softmac_on_assoc_rsp; ++ priv->ieee80211->ext_patch_ieee80211_ext_stop_scan_wq_set_channel = priv->mshobj->ext_patch_ieee80211_ext_stop_scan_wq_set_channel; ++ priv->ieee80211->ext_patch_ieee80211_process_probe_response_1 = priv->mshobj->ext_patch_ieee80211_process_probe_response_1; ++ priv->ieee80211->ext_patch_ieee80211_rx_mgt_on_probe_req = priv->mshobj->ext_patch_ieee80211_rx_mgt_on_probe_req; ++ priv->ieee80211->ext_patch_ieee80211_rx_mgt_update_expire = priv->mshobj->ext_patch_ieee80211_rx_mgt_update_expire; ++ priv->ieee80211->ext_patch_get_beacon_get_probersp = priv->mshobj->ext_patch_get_beacon_get_probersp; ++ priv->ieee80211->ext_patch_ieee80211_rx_on_rx = priv->mshobj->ext_patch_ieee80211_rx_on_rx; ++ priv->ieee80211->ext_patch_ieee80211_xmit = priv->mshobj->ext_patch_ieee80211_xmit; ++ priv->ieee80211->ext_patch_ieee80211_rx_frame_get_hdrlen = priv->mshobj->ext_patch_ieee80211_rx_frame_get_hdrlen; ++ priv->ieee80211->ext_patch_ieee80211_rx_is_valid_framectl = priv->mshobj->ext_patch_ieee80211_rx_is_valid_framectl; ++ priv->ieee80211->ext_patch_ieee80211_rx_process_dataframe = priv->mshobj->ext_patch_ieee80211_rx_process_dataframe; ++ // priv->ieee80211->ext_patch_is_duplicate_packet = priv->mshobj->ext_patch_is_duplicate_packet; ++ priv->ieee80211->ext_patch_ieee80211_softmac_xmit_get_rate = priv->mshobj->ext_patch_ieee80211_softmac_xmit_get_rate; ++ /* added by david for setting acl dynamically */ ++ priv->ieee80211->ext_patch_ieee80211_acl_query = priv->mshobj->ext_patch_ieee80211_acl_query; ++ } ++ ++#endif // _RTL8187_EXT_PATCH_ ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ INIT_WORK(&priv->ieee80211->wmm_param_update_wq,\ ++ (void(*)(void*)) rtl8180_wmm_param_update,\ ++ priv->ieee80211); ++#else ++ INIT_WORK(&priv->ieee80211->wmm_param_update_wq,\ ++ rtl8180_wmm_param_update); ++#endif ++#else ++ tq_init(&priv->ieee80211->wmm_param_update_wq,\ ++ (void(*)(void*)) rtl8180_wmm_param_update,\ ++ priv->ieee80211); ++#endif ++ priv->ieee80211->init_wmmparam_flag = 0; ++ priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD; ++ ++ //priv->card_8185 = 2; ++ priv->phy_ver = 2; ++ priv->card_type = USB; ++//{add for 87B ++ priv->ShortRetryLimit = 7; ++ priv->LongRetryLimit = 7; ++ priv->EarlyRxThreshold = 7; ++ ++ priv->TransmitConfig = ++ TCR_DurProcMode | //for RTL8185B, duration setting by HW ++ TCR_DISReqQsize | ++ (TCR_MXDMA_2048<ShortRetryLimit<LongRetryLimit<ReceiveConfig = ++ RCR_AMF | RCR_ADF | //accept management/data ++ RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko. ++ RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC ++ //RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet ++ RCR_MXDMA | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited. ++ (priv->EarlyRxThreshold<EarlyRxThreshold == 7 ? RCR_ONLYERLPKT:0); ++ ++ priv->AcmControl = 0; ++//} ++ priv->rf_chip = 0xff & eprom_read(dev,EPROM_RFCHIPID); ++ //DMESG("rf_chip:%x\n", priv->rf_chip); ++ if (!priv->rf_chip) ++ { ++ DMESG("Can't get rf chip ID from EEPROM"); ++ DMESGW("So set rf chip ID to defalut EPROM_RFCHIPID_RTL8225U"); ++ DMESGW("use it with care and at your own risk and"); ++ DMESGW("**PLEASE** REPORT SUCCESS/INSUCCESS TO Realtek"); ++ priv->rf_chip = EPROM_RFCHIPID_RTL8225U; ++ ++ } ++ ++ ++//{put the card to detect different card here, mainly I/O processing ++ udev = priv->udev; ++ idProduct = le16_to_cpu(udev->descriptor.idProduct); ++ //idProduct = 0x8197; ++ bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice); ++ DMESG("idProduct:0x%x, bcdDevice:0x%x", idProduct,bcdDevice); ++ switch (idProduct) { ++ case 0x8189: ++ case 0x8197: ++ case 0x8198: ++ /* check RF frontend chipset */ ++ priv->card_8187 = NIC_8187B; ++ priv->rf_init = rtl8225z2_rf_init; ++ priv->rf_set_chan = rtl8225z2_rf_set_chan; ++ priv->rf_set_sens = NULL; ++ break; ++ ++ case 0x8187: ++ if(bcdDevice == 0x0200){ ++ priv->card_8187 = NIC_8187B; ++ priv->rf_init = rtl8225z2_rf_init; ++ priv->rf_set_chan = rtl8225z2_rf_set_chan; ++ priv->rf_set_sens = NULL; ++ break; ++ }else{ ++ //0x0100 is for 8187 ++ //legacy 8187 NIC ++ //delet ++ ; ++ } ++ default: ++ /* check RF frontend chipset */ ++ priv->ieee80211->softmac_features |= IEEE_SOFTMAC_SINGLE_QUEUE; ++ priv->card_8187 = NIC_8187; ++ switch (priv->rf_chip) { ++ case EPROM_RFCHIPID_RTL8225U: ++ DMESG("Card reports RF frontend Realtek 8225"); ++ DMESGW("This driver has EXPERIMENTAL support for this chipset."); ++ DMESGW("use it with care and at your own risk and"); ++ DMESGW("**PLEASE** REPORT SUCCESS/INSUCCESS TO Realtek"); ++ if(rtl8225_is_V_z2(dev)){ ++ priv->rf_init = rtl8225z2_rf_init; ++ priv->rf_set_chan = rtl8225z2_rf_set_chan; ++ priv->rf_set_sens = NULL; ++ DMESG("This seems a new V2 radio"); ++ }else{ ++ priv->rf_init = rtl8225_rf_init; ++ priv->rf_set_chan = rtl8225_rf_set_chan; ++ priv->rf_set_sens = rtl8225_rf_set_sens; ++ DMESG("This seems a legacy 1st version radio"); ++ } ++ break; ++ ++ case EPROM_RFCHIPID_RTL8225U_VF: ++ priv->rf_init = rtl8225z2_rf_init; ++ priv->rf_set_chan = rtl8225z2_rf_set_chan; ++ priv->rf_set_sens = NULL; ++ DMESG("This seems a new V2 radio"); ++ break; ++ ++ default: ++ DMESGW("Unknown RF module %x",priv->rf_chip); ++ DMESGW("Exiting..."); ++ return -1; ++ } ++ break; ++ } ++ ++ priv->rf_close = rtl8225_rf_close; ++ priv->max_sens = RTL8225_RF_MAX_SENS; ++ priv->sens = RTL8225_RF_DEF_SENS; ++ ++#ifdef ENABLE_DOT11D ++#if 0 ++ for(i=0;i<0xFF;i++) { ++ if(i%16 == 0) ++ printk("\n[%x]: ", i/16); ++ printk("\t%4.4x", eprom_read(dev,i)); ++ } ++#endif ++ priv->channel_plan = eprom_read(dev,EPROM_CHANNEL_PLAN) & 0xFF; ++ //DMESG("EPROM_CHANNEL_PLAN is %x", priv->channel_plan); ++ ++ // lzm add 081205 for Toshiba: ++ // For Toshiba,reading the value from EEPROM 0x6h bit[7] to determine the priority of ++ // channel plan to be defined. ++ // -If bit[7] is true, then the channel plan is defined by EEPROM but no user defined. ++ // -If bit[7] is false, then the channel plan is defined by user first. ++ // ++ if(priv->channel_plan & 0x80) { ++ DMESG("Toshiba channel plan is defined by EEPROM"); ++ priv->channel_plan &= 0xf; ++ } ++ else ++ priv->channel_plan = 0; ++ ++ //if(priv->channel_plan > COUNTRY_CODE_WORLD_WIDE_13_INDEX){ ++ if(priv->channel_plan > COUNTRY_CODE_GLOBAL_DOMAIN){ ++ DMESG("rtl8180_init:Error channel plan! Set to default.\n"); ++ priv->channel_plan = 0; ++ } ++ ++ //priv->channel_plan = 9; //Global Domain ++ //priv->channel_plan = 2; //ETSI ++ ++ ++ DMESG("Channel plan is %d ",priv->channel_plan); ++ ++ //for Toshiba card we read channel plan from ChanPlanBin ++ if((idProduct != 0x8197) && (idProduct != 0x8198)) ++ rtl8180_set_channel_map(priv->channel_plan, priv->ieee80211); ++#else ++ int ch; ++ priv->channel_plan = eprom_read(dev,EPROM_CHANNEL_PLAN) & 0xff; ++ if(priv->channel_plan & 0x80) { ++ priv->channel_plan &= 0x7f; ++ if (ChannelPlan[priv->channel_plan].Len != 0){ ++ // force channel plan map ++ for (i=0;ichannel_plan].Len;i++) ++ priv->ieee80211->channel_map[ChannelPlan[priv->channel_plan].Channel[i]] = 1; ++ } else { ++ DMESG("No channels, aborting"); ++ return -1; ++ } ++ } else { ++ //default channel plan setting ++ if(!channels){ ++ DMESG("No channels, aborting"); ++ return -1; ++ } ++ ch=channels; ++ // set channels 1..14 allowed in given locale ++ for (i=1; i<=14; i++) { ++ (priv->ieee80211->channel_map)[i] = (u8)(ch & 0x01); ++ ch >>= 1; ++ } ++ } ++#endif ++ ++ if((idProduct == 0x8197) || (idProduct == 0x8198)) { ++ // lzm add 081205 for Toshiba: ++ // 0x77h bit[0]=1: use GPIO bit[2], bit[0]=0: use GPIO bit[1] ++ priv->EEPROMSelectNewGPIO =((u8)((eprom_read(dev,EPROM_SELECT_GPIO) & 0xff00) >> 8)) ? true : false; ++ DMESG("EPROM_SELECT_GPIO:%d", priv->EEPROMSelectNewGPIO); ++ } else { ++ priv->EEPROMSelectNewGPIO = false; ++ } ++ ++ ++ if (NIC_8187 == priv->card_8187){ ++ hw_version =( read_nic_dword(dev, TCR) & TCR_HWVERID_MASK)>>TCR_HWVERID_SHIFT; ++ switch (hw_version) { ++ case 0x06: ++ //priv->card_8187_Bversion = VERSION_8187B_B; ++ break; ++ case 0x05: ++ priv->card_8187_Bversion = VERSION_8187_D; ++ break; ++ default: ++ priv->card_8187_Bversion = VERSION_8187_B; ++ break; ++ } ++ }else{ ++ hw_version = read_nic_byte(dev, 0xe1); //87B hw version reg ++ switch (hw_version){ ++ case 0x00: ++ priv->card_8187_Bversion = VERSION_8187B_B; ++ break; ++ case 0x01: ++ priv->card_8187_Bversion = VERSION_8187B_D; ++ break; ++ case 0x02: ++ priv->card_8187_Bversion = VERSION_8187B_E; ++ break; ++ default: ++ priv->card_8187_Bversion = VERSION_8187B_B; //defalt ++ break; ++ } ++ } ++ ++ //printk("=====hw_version:%x\n", priv->card_8187_Bversion); ++ priv->enable_gpio0 = 0; ++ ++ /*the eeprom type is stored in RCR register bit #6 */ ++ if (RCR_9356SEL & read_nic_dword(dev, RCR)){ ++ priv->epromtype=EPROM_93c56; ++ DMESG("Reported EEPROM chip is a 93c56 (2Kbit)"); ++ }else{ ++ priv->epromtype=EPROM_93c46; ++ DMESG("Reported EEPROM chip is a 93c46 (1Kbit)"); ++ } ++ ++ dev->dev_addr[0]=eprom_read(dev,MAC_ADR) & 0xff; ++ dev->dev_addr[1]=(eprom_read(dev,MAC_ADR) & 0xff00)>>8; ++ dev->dev_addr[2]=eprom_read(dev,MAC_ADR+1) & 0xff; ++ dev->dev_addr[3]=(eprom_read(dev,MAC_ADR+1) & 0xff00)>>8; ++ dev->dev_addr[4]=eprom_read(dev,MAC_ADR+2) & 0xff; ++ dev->dev_addr[5]=((eprom_read(dev,MAC_ADR+2) & 0xff00)>>8)+1; ++ ++ DMESG("Card MAC address is "MAC_FMT, MAC_ARG(dev->dev_addr)); ++ ++ for(i=1,j=0; i<6; i+=2,j++){ ++ ++ word = eprom_read(dev,EPROM_TXPW0 + j); ++ priv->chtxpwr[i]=word & 0xf; ++ priv->chtxpwr_ofdm[i]=(word & 0xf0)>>4; ++ priv->chtxpwr[i+1]=(word & 0xf00)>>8; ++ priv->chtxpwr_ofdm[i+1]=(word & 0xf000)>>12; ++ } ++ ++ for(i=1,j=0; i<4; i+=2,j++){ ++ ++ word = eprom_read(dev,EPROM_TXPW1 + j); ++ priv->chtxpwr[i+6]=word & 0xf; ++ priv->chtxpwr_ofdm[i+6]=(word & 0xf0)>>4; ++ priv->chtxpwr[i+6+1]=(word & 0xf00)>>8; ++ priv->chtxpwr_ofdm[i+6+1]=(word & 0xf000)>>12; ++ } ++ if (priv->card_8187 == NIC_8187){ ++ for(i=1,j=0; i<4; i+=2,j++){ ++ word = eprom_read(dev,EPROM_TXPW2 + j); ++ priv->chtxpwr[i+6+4]=word & 0xf; ++ priv->chtxpwr_ofdm[i+6+4]=(word & 0xf0)>>4; ++ priv->chtxpwr[i+6+4+1]=(word & 0xf00)>>8; ++ priv->chtxpwr_ofdm[i+6+4+1]=(word & 0xf000)>>12; ++ } ++ } else{ ++ word = eprom_read(dev, 0x1B) & 0xff; //channel 11; ++ priv->chtxpwr[11]=word & 0xf; ++ priv->chtxpwr_ofdm[11] = (word & 0xf0)>>4; ++ ++ word = eprom_read(dev, 0xA) & 0xff; //channel 12; ++ priv->chtxpwr[12]=word & 0xf; ++ priv->chtxpwr_ofdm[12] = (word & 0xf0)>>4; ++ ++ word = eprom_read(dev, 0x1c) ; //channel 13 ,14; ++ priv->chtxpwr[13]=word & 0xf; ++ priv->chtxpwr_ofdm[13] = (word & 0xf0)>>4; ++ priv->chtxpwr[14]=(word & 0xf00)>>8; ++ priv->chtxpwr_ofdm[14] = (word & 0xf000)>>12; ++ } ++ ++ word = eprom_read(dev,EPROM_TXPW_BASE); ++ priv->cck_txpwr_base = word & 0xf; ++ priv->ofdm_txpwr_base = (word>>4) & 0xf; ++ ++ //DMESG("PAPE from CONFIG2: %x",read_nic_byte(dev,CONFIG2)&0x7); ++ ++#ifdef SW_ANTE_DIVERSITY ++ rtl8187_antenna_diversity_read(dev); ++#endif ++ ++ if(rtl8187_usb_initendpoints(dev)!=0){ ++ DMESG("Endopoints initialization failed"); ++ return -ENOMEM; ++ } ++#ifdef LED ++ InitSwLeds(dev); ++#endif ++#ifdef DEBUG_EPROM ++ dump_eprom(dev); ++#endif ++ return 0; ++ ++} ++ ++void rtl8185_rf_pins_enable(struct net_device *dev) ++{ ++/* u16 tmp; ++ tmp = read_nic_word(dev, RFPinsEnable);*/ ++ write_nic_word(dev, RFPinsEnable, 0x1ff7);// | tmp); ++} ++ ++ ++void rtl8185_set_anaparam2(struct net_device *dev, u32 a) ++{ ++ u8 conf3; ++ ++ rtl8180_set_mode(dev, EPROM_CMD_CONFIG); ++ ++ conf3 = read_nic_byte(dev, CONFIG3); ++ write_nic_byte(dev, CONFIG3, conf3 | (1<> 24)); ++ write_nic_byte(dev, 0x7e, ((phyw & 0x00ff0000) >> 16)); ++ write_nic_byte(dev, 0x7d, ((phyw & 0x0000ff00) >> 8)); ++ write_nic_byte(dev, 0x7c, ((phyw & 0x000000ff) )); ++ ++ //read_nic_dword(dev, PHY_ADR); ++#if 0 ++ for(i=0;i<10;i++){ ++ write_nic_dword(dev, PHY_ADR, 0xffffff7f & phyw); ++ phyr = read_nic_byte(dev, PHY_READ); ++ if(phyr == (data&0xff)) break; ++ ++ } ++#endif ++ /* this is ok to fail when we write AGC table. check for AGC table might be ++ * done by masking with 0x7f instead of 0xff */ ++ //if(phyr != (data&0xff)) DMESGW("Phy write timeout %x %x %x", phyr, data, adr); ++ //msdelay(1);//CPU occupany is too high. LZM 31/10/2008 ++} ++ ++u8 rtl8187_read_phy(struct net_device *dev,u8 adr, u32 data) ++{ ++ u32 phyw; ++ ++ adr &= ~0x80; ++ phyw= ((data<<8) | adr); ++ ++ ++ // Note that, we must write 0xff7c after 0x7d-0x7f to write BB register. ++ write_nic_byte(dev, 0x7f, ((phyw & 0xff000000) >> 24)); ++ write_nic_byte(dev, 0x7e, ((phyw & 0x00ff0000) >> 16)); ++ write_nic_byte(dev, 0x7d, ((phyw & 0x0000ff00) >> 8)); ++ write_nic_byte(dev, 0x7c, ((phyw & 0x000000ff) )); ++ ++ return(read_nic_byte(dev,0x7e)); ++ ++} ++ ++u8 read_phy_ofdm(struct net_device *dev, u8 adr) ++{ ++ return(rtl8187_read_phy(dev, adr, 0x000000)); ++} ++ ++u8 read_phy_cck(struct net_device *dev, u8 adr) ++{ ++ return(rtl8187_read_phy(dev, adr, 0x10000)); ++} ++ ++inline void write_phy_ofdm (struct net_device *dev, u8 adr, u32 data) ++{ ++ data = data & 0xff; ++ rtl8187_write_phy(dev, adr, data); ++} ++ ++ ++void write_phy_cck (struct net_device *dev, u8 adr, u32 data) ++{ ++ data = data & 0xff; ++ rtl8187_write_phy(dev, adr, data | 0x10000); ++} ++// ++// Description: Change ZEBRA's power state. ++// ++// Assumption: This function must be executed in PASSIVE_LEVEL. ++// ++// 061214, by rcnjko. ++// ++//#define MAX_DOZE_WAITING_TIMES_87B 1000//500 ++#define MAX_DOZE_WAITING_TIMES_87B_MOD 500 ++ ++bool SetZebraRFPowerState8187B(struct net_device *dev,RT_RF_POWER_STATE eRFPowerState) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u8 btCR9346, btConfig3; ++ bool bResult = true; ++ int i; ++ u16 u2bTFPC = 0; ++ u8 u1bTmp; ++ ++ // Set EEM0 and EEM1 in 9346CR. ++ btCR9346 = read_nic_byte(dev, CR9346); ++ write_nic_byte(dev, CR9346, (btCR9346|0xC0) ); ++ // Set PARM_En in Config3. ++ btConfig3 = read_nic_byte(dev, CONFIG3); ++ write_nic_byte(dev, CONFIG3, (btConfig3|CONFIG3_PARM_En) ); ++ // BB and RF related operations: ++ switch(eRFPowerState) ++ { ++ case eRfOn: ++//#ifdef CONFIG_RADIO_DEBUG ++ DMESG("Now Radio ON!"); ++//#endif ++ write_nic_dword(dev, ANAPARAM, ANAPARM_ON); ++ write_nic_dword(dev, ANAPARAM2, ANAPARM2_ON); ++ //write_nic_byte(dev, CONFIG4, (priv->RFProgType)); ++ ++ write_nic_byte(dev, 0x085, 0x24); // 061219, SD3 ED: for minicard CCK power leakage issue. ++ write_rtl8225(dev, 0x4, 0x9FF); ++ mdelay(1); ++ // ++ // We reset PLL to reduce power consumption about 30 mA. 2008.01.16. ++ // ++ { ++ u8 Reg62; ++ ++ write_nic_byte(dev, 0x61, 0x10); ++ Reg62 = read_nic_byte(dev, 0x62); ++ write_nic_byte(dev, 0x62, (Reg62 & (~BIT5)) ); ++ write_nic_byte(dev, 0x62, (Reg62 | BIT5) ); // Enable PLL. ++ } ++ ++ u1bTmp = read_nic_byte(dev, 0x24E); ++ write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5|BIT6))) );// 070124 SD1 Alex: turn on CCK and OFDM. ++ break; ++ ++ case eRfSleep: ++#ifdef CONFIG_RADIO_DEBUG ++ DMESG("Now Radio Sleep!"); ++#endif ++ for(i = 0; i < MAX_DOZE_WAITING_TIMES_87B_MOD; i++) ++ { // Make sure TX FIFO is empty befor turn off RFE pwoer. ++ u2bTFPC = read_nic_word(dev, TFPC); ++ if(u2bTFPC == 0){ ++ printk("%d times TFPC: %d == 0 before doze...\n", (i+1), u2bTFPC); ++ break; ++ }else{ ++ printk("%d times TFPC: %d != 0 before doze!\n", (i+1), u2bTFPC); ++ udelay(10); ++ } ++ } ++ ++ if( i == MAX_DOZE_WAITING_TIMES_87B_MOD ){ ++ printk("\n\n\n SetZebraRFPowerState8187B(): %d times TFPC: %d != 0 !!!\n\n\n", MAX_DOZE_WAITING_TIMES_87B_MOD, u2bTFPC); ++ } ++ ++ u1bTmp = read_nic_byte(dev, 0x24E); ++ write_nic_byte(dev, 0x24E, (u1bTmp|BIT5|BIT6));// 070124 SD1 Alex: turn off CCK and OFDM. ++ ++ write_rtl8225(dev, 0x4, 0xDFF); // Turn off RF first to prevent BB lock up, suggested by PJ, 2006.03.03. ++ write_nic_byte(dev, 0x085, 0x04); // 061219, SD3 ED: for minicard CCK power leakage issue. ++ ++ //write_nic_byte(dev, CONFIG4, (priv->RFProgType|Config4_PowerOff)); ++ ++ write_nic_dword(dev, ANAPARAM, ANAPARM_OFF); ++ write_nic_dword(dev, ANAPARAM2, 0x72303f70); // 070126, by SD1 William. ++ break; ++ ++ case eRfOff: ++//#ifdef CONFIG_RADIO_DEBUG ++ DMESG("Now Radio OFF!"); ++//#endif ++ for(i = 0; i < MAX_DOZE_WAITING_TIMES_87B_MOD; i++) ++ { // Make sure TX FIFO is empty befor turn off RFE pwoer. ++ u2bTFPC = read_nic_word(dev, TFPC); ++ if(u2bTFPC == 0) { ++ //printk("%d times TFPC: %d == 0 before doze...\n", (i+1), u2bTFPC); ++ break; ++ }else{ ++ //printk("%d times TFPC: 0x%x != 0 before doze!\n", (i+1), u2bTFPC); ++ udelay(10); ++ } ++ } ++ ++ if( i == MAX_DOZE_WAITING_TIMES_87B_MOD){ ++ printk("\n\n\nSetZebraRFPowerState8187B(): %d times TFPC: 0x%x != 0 !!!\n\n\n", MAX_DOZE_WAITING_TIMES_87B_MOD, u2bTFPC); ++ } ++ ++ u1bTmp = read_nic_byte(dev, 0x24E); ++ write_nic_byte(dev, 0x24E, (u1bTmp|BIT5|BIT6));// 070124 SD1 Alex: turn off CCK and OFDM. ++ ++ write_rtl8225(dev, 0x4,0x1FF); // Turn off RF first to prevent BB lock up, suggested by PJ, 2006.03.03. ++ write_nic_byte(dev, 0x085, 0x04); // 061219, SD3 ED: for minicard CCK power leakage issue. ++ ++ //write_nic_byte(dev, CONFIG4, (priv->RFProgType|Config4_PowerOff)); ++ ++ write_nic_dword(dev, ANAPARAM, ANAPARM_OFF); ++ write_nic_dword(dev, ANAPARAM2, ANAPARM2_OFF); // 070301, SD1 William: to reduce RF off power consumption to 80 mA. ++ break; ++ ++ default: ++ bResult = false; ++ printk("SetZebraRFPowerState8187B(): unknow state to set: 0x%X!!!\n", eRFPowerState); ++ break; ++ } ++ ++ // Clear PARM_En in Config3. ++ btConfig3 &= ~(CONFIG3_PARM_En); ++ write_nic_byte(dev, CONFIG3, btConfig3); ++ // Clear EEM0 and EEM1 in 9346CR. ++ btCR9346 &= ~(0xC0); ++ write_nic_byte(dev, CR9346, btCR9346); ++ ++ if(bResult){ ++ // Update current RF state variable. ++ priv->eRFPowerState = eRFPowerState; ++ } ++ ++ return bResult; ++} ++//by amy for ps ++// ++// Description: Chang RF Power State. ++// Note that, only MgntActSet_RF_State() is allowed to set HW_VAR_RF_STATE. ++// ++// Assumption:PASSIVE LEVEL. ++// ++bool SetRFPowerState(struct net_device *dev,RT_RF_POWER_STATE eRFPowerState) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ bool bResult = false; ++ ++ //printk("---------> SetRFPowerState(): eRFPowerState(%d)\n", eRFPowerState); ++ if(eRFPowerState == priv->eRFPowerState) ++ { ++ //printk("<--------- SetRFPowerState(): discard the request for eRFPowerState(%d) is the same.\n", eRFPowerState); ++ return bResult; ++ } ++ ++ switch(priv->rf_chip) ++ { ++ case RF_ZEBRA2: ++ bResult = SetZebraRFPowerState8187B(dev, eRFPowerState); ++ break; ++ ++ default: ++ printk("SetRFPowerState8185(): unknown RFChipID: 0x%X!!!\n", priv->rf_chip); ++ break;; ++ } ++ //printk("<--------- SetRFPowerState(): bResult(%d)\n", bResult); ++ ++ return bResult; ++} ++ ++bool ++MgntActSet_RF_State(struct net_device *dev,RT_RF_POWER_STATE StateToSet,u32 ChangeSource) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ bool bActionAllowed = false; ++ bool bConnectBySSID = false; ++ RT_RF_POWER_STATE rtState; ++ u16 RFWaitCounter = 0; ++ unsigned long flag; ++ // printk("===>MgntActSet_RF_State(): StateToSet(%d), ChangeSource(0x%x)\n",StateToSet, ChangeSource); ++ // ++ // Prevent the race condition of RF state change. By Bruce, 2007-11-28. ++ // Only one thread can change the RF state at one time, and others should wait to be executed. ++ // ++#if 1 ++ while(true) ++ { ++ //down(&priv->rf_state); ++ spin_lock_irqsave(&priv->rf_ps_lock,flag); ++ if(priv->RFChangeInProgress) ++ { ++ //up(&priv->rf_state); ++ //RT_TRACE(COMP_RF, DBG_LOUD, ("MgntActSet_RF_State(): RF Change in progress! Wait to set..StateToSet(%d).\n", StateToSet)); ++ spin_unlock_irqrestore(&priv->rf_ps_lock,flag); ++ // Set RF after the previous action is done. ++ while(priv->RFChangeInProgress) ++ { ++ RFWaitCounter ++; ++ //RT_TRACE(COMP_RF, DBG_LOUD, ("MgntActSet_RF_State(): Wait 1 ms (%d times)...\n", RFWaitCounter)); ++ udelay(1000); // 1 ms ++ ++ // Wait too long, return FALSE to avoid to be stuck here. ++ if(RFWaitCounter > 1000) // 1sec ++ { ++ DMESG("MgntActSet_RF_State(): Wait too long to set RF"); ++ // TODO: Reset RF state? ++ return false; ++ } ++ } ++ } ++ else ++ { ++ priv->RFChangeInProgress = true; ++// up(&priv->rf_state); ++ spin_unlock_irqrestore(&priv->rf_ps_lock,flag); ++ break; ++ } ++ } ++#endif ++ rtState = priv->eRFPowerState; ++ ++ switch(StateToSet) ++ { ++ case eRfOn: ++ // ++ // Turn On RF no matter the IPS setting because we need to update the RF state to Ndis under Vista, or ++ // the Windows does not allow the driver to perform site survey any more. By Bruce, 2007-10-02. ++ // ++ // leave last reasons and kick this reason till priv->RfOffReason = 0; ++ // if one reason turn radio off check if off->on reason is the same.if so turn, or reject it. ++ // if more than 1 reasons turn radio off we only turn on radio when all reasons turn on radio, ++ // so first turn on trys will reject till priv->RfOffReason = 0; ++ priv->RfOffReason &= (~ChangeSource); ++ ++ if(! priv->RfOffReason) ++ { ++ priv->RfOffReason = 0; ++ bActionAllowed = true; ++ ++ if(rtState == eRfOff && ChangeSource >=RF_CHANGE_BY_HW && !priv->bInHctTest) ++ { ++ bConnectBySSID = true; ++ } ++ } else { ++ ;//lzm must or TX_PENDING 12>MAX_TX_URB ++ //printk("Turn Radio On Reject because RfOffReason= 0x%x, ChangeSource=0x%X\n", priv->RfOffReason, ChangeSource); ++ } ++ break; ++ ++ case eRfOff: ++ // 070125, rcnjko: we always keep connected in AP mode. ++ if (priv->RfOffReason > RF_CHANGE_BY_IPS) ++ { ++ // ++ // 060808, Annie: ++ // Disconnect to current BSS when radio off. Asked by QuanTa. ++ // ++ ++ // ++ // Calling MgntDisconnect() instead of MgntActSet_802_11_DISASSOCIATE(), ++ // because we do NOT need to set ssid to dummy ones. ++ // Revised by Roger, 2007.12.04. ++ // ++//by amy not supported ++ //MgntDisconnect( dev, disas_lv_ss ); ++ ++ // Clear content of bssDesc[] and bssDesc4Query[] to avoid reporting old bss to UI. ++ // 2007.05.28, by shien chang. ++ //PlatformZeroMemory( pMgntInfo->bssDesc, sizeof(RT_WLAN_BSS)*MAX_BSS_DESC ); ++ //pMgntInfo->NumBssDesc = 0; ++ //PlatformZeroMemory( pMgntInfo->bssDesc4Query, sizeof(RT_WLAN_BSS)*MAX_BSS_DESC ); ++ //pMgntInfo->NumBssDesc4Query = 0; ++ } ++ ++ ++ ++ priv->RfOffReason |= ChangeSource; ++ bActionAllowed = true; ++ //printk("Turn Radio Off RfOffReason= 0x%x, ChangeSource=0x%X\n", priv->RfOffReason, ChangeSource); ++ break; ++ ++ case eRfSleep: ++ priv->RfOffReason |= ChangeSource; ++ bActionAllowed = true; ++ break; ++ ++ default: ++ break; ++ } ++ ++ if(bActionAllowed) ++ { ++ // Config HW to the specified mode. ++ //printk("MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", StateToSet, priv->RfOffReason); ++ SetRFPowerState(dev, StateToSet); ++ // Turn on RF. ++ if(StateToSet == eRfOn) ++ { ++ //HalEnableRx8185Dummy(dev); ++ if(bConnectBySSID) ++ { ++ // by amy not supported ++ //MgntActSet_802_11_SSID(Adapter, Adapter->MgntInfo.Ssid.Octet, Adapter->MgntInfo.Ssid.Length, TRUE ); ++ } ++ } ++ // Turn off RF. ++ else if(StateToSet == eRfOff) ++ { ++ //HalDisableRx8185Dummy(dev); ++ } ++ } ++ else ++ { ++ //printk("Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n", ++ // StateToSet, ChangeSource, priv->RfOffReason); ++ } ++ ++ // Release RF spinlock ++ //down(&priv->rf_state); ++ spin_lock_irqsave(&priv->rf_ps_lock,flag); ++ priv->RFChangeInProgress = false; ++ //up(&priv->rf_state); ++ spin_unlock_irqrestore(&priv->rf_ps_lock,flag); ++ return bActionAllowed; ++} ++//by amy for ps ++ ++void rtl8180_adapter_start(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++// struct ieee80211_device *ieee = priv->ieee80211; ++// u8 InitWirelessMode; ++// u8 SupportedWirelessMode; ++// bool bInvalidWirelessMode = false; ++ ++ ++ if(NIC_8187 == priv->card_8187) { ++ //rtl8180_rtx_disable(dev); ++ rtl8180_reset(dev); ++ ++ write_nic_byte(dev,0x85,0); ++ write_nic_byte(dev,0x91,0); ++ ++ /* light blink! */ ++ write_nic_byte(dev,0x85,4); ++ write_nic_byte(dev,0x91,1); ++ write_nic_byte(dev,0x90,0); ++ ++ //by lizhaoming for LED POWR ON ++ //LedControl8187(dev, LED_CTL_POWER_ON); ++ ++ /* ++ write_nic_byte(dev, CR9346, 0xC0); ++ //LED TYPE ++ write_nic_byte(dev, CONFIG1,((read_nic_byte(dev, CONFIG1)&0x3f)|0x80)); //turn on bit 5:Clkrun_mode ++ write_nic_byte(dev, CR9346, 0x0); // disable config register write ++ */ ++ priv->irq_mask = 0xffff; ++ /* ++ priv->dma_poll_mask = 0; ++ priv->dma_poll_mask|= (1<dev_addr)[0]); ++ write_nic_word(dev, MAC4, ((u32*)dev->dev_addr)[1] & 0xffff ); ++ ++ rtl8180_set_mode(dev, EPROM_CMD_NORMAL); ++ rtl8180_update_msr(dev); ++ ++ rtl8180_set_mode(dev, EPROM_CMD_CONFIG); ++ ++ write_nic_word(dev,0xf4,0xffff); ++ write_nic_byte(dev, ++ CONFIG1, (read_nic_byte(dev,CONFIG1) & 0x3f) | 0x80); ++ ++ rtl8180_set_mode(dev,EPROM_CMD_NORMAL); ++ ++ write_nic_dword(dev,INT_TIMEOUT,0); ++ ++#ifdef DEBUG_REGISTERS ++ rtl8180_dump_reg(dev); ++#endif ++ ++ ++ write_nic_byte(dev, WPA_CONFIG, 0); ++ ++ write_nic_byte(dev, RATE_FALLBACK, 0x81); ++ rtl8187_set_rate(dev); ++ ++ priv->rf_init(dev); ++ ++ if(priv->rf_set_sens != NULL) { ++ priv->rf_set_sens(dev,priv->sens); ++ } ++ ++ write_nic_word(dev,0x5e,1); ++ //mdelay(1); ++ write_nic_word(dev,0xfe,0x10); ++ // mdelay(1); ++ write_nic_byte(dev, TALLY_SEL, 0x80);//Set NQ retry count ++ write_nic_byte(dev, 0xff, 0x60); ++ write_nic_word(dev,0x5e,0); ++ ++ rtl8180_irq_enable(dev); ++ } else { ++ /** ++ * IO part migrated from Windows Driver. ++ */ ++ priv->irq_mask = 0xffff; ++ // Enable Config3.PARAM_En. ++ write_nic_byte(dev, CR9346, 0xC0); ++ ++ write_nic_byte(dev, CONFIG3, (read_nic_byte(dev, CONFIG3)| CONFIG3_PARM_En|CONFIG3_GNTSel)); ++ // Turn on Analog power. ++ // setup A/D D/A parameter for 8185 b2 ++ // Asked for by William, otherwise, MAC 3-wire can't work, 2006.06.27, by rcnjko. ++ write_nic_dword(dev, ANA_PARAM2, ANAPARM2_ASIC_ON); ++ write_nic_dword(dev, ANA_PARAM, ANAPARM_ASIC_ON); ++ write_nic_byte(dev, ANA_PARAM3, 0x00); ++ ++ //by lizhaoming for LED POWR ON ++ //LedControl8187(dev, LED_CTL_POWER_ON); ++ ++ {//added for reset PLL ++ u8 bReg62; ++ write_nic_byte(dev, 0x61, 0x10); ++ bReg62 = read_nic_byte(dev, 0x62); ++ write_nic_byte(dev, 0x62, bReg62&(~(0x1<<5))); ++ write_nic_byte(dev, 0x62, bReg62|(0x1<<5)); ++ } ++ write_nic_byte(dev, CONFIG3, (read_nic_byte(dev, CONFIG3)&(~CONFIG3_PARM_En))); ++ write_nic_byte(dev, CR9346, 0x00); ++ ++ //rtl8180_rtx_disable(dev); ++ rtl8180_reset(dev); ++ write_nic_byte(dev, CR9346, 0xc0); // enable config register write ++ priv->rf_init(dev); ++ // Enable tx/rx ++ ++ write_nic_byte(dev, CMD, (CR_RE|CR_TE));// Using HW_VAR_COMMAND instead of writing CMDR directly. Rewrited by Annie, 2006-04-07. ++ ++ //add this is for 8187B Rx stall problem ++ ++ rtl8180_irq_enable(dev); ++ ++ write_nic_byte_E(dev, 0x41, 0xF4); ++ write_nic_byte_E(dev, 0x40, 0x00); ++ write_nic_byte_E(dev, 0x42, 0x00); ++ write_nic_byte_E(dev, 0x42, 0x01); ++ write_nic_byte_E(dev, 0x40, 0x0F); ++ write_nic_byte_E(dev, 0x42, 0x00); ++ write_nic_byte_E(dev, 0x42, 0x01); ++ ++ // 8187B demo board MAC and AFE power saving parameters from SD1 William, 2006.07.20. ++ // Parameter revised by SD1 William, 2006.08.21: ++ // 373h -> 0x4F // Original: 0x0F ++ // 377h -> 0x59 // Original: 0x4F ++ // Victor 2006/8/21: ¬Ù¹q°Ñ¼Æ«Øijµ¥SD3 °ª§C·Å and cable link test OK¤~¥¿¦¡ release,¤£«Øij¤Ó§Ö ++ // 2006/9/5, Victor & ED: it is OK to use. ++ //if(pHalData->RegBoardType == BT_DEMO_BOARD) ++ //{ ++ // AFE. ++ // ++ // Revise the content of Reg0x372, 0x374, 0x378 and 0x37a to fix unusual electronic current ++ // while CTS-To-Self occurs, by DZ's request. ++ // Modified by Roger, 2007.06.22. ++ // ++ write_nic_byte(dev, 0x0DB, (read_nic_byte(dev, 0x0DB)|(BIT2))); ++ write_nic_word(dev, 0x372, 0x59FA); // 0x4FFA-> 0x59FA. ++ write_nic_word(dev, 0x374, 0x59D2); // 0x4FD2-> 0x59D2. ++ write_nic_word(dev, 0x376, 0x59D2); ++ write_nic_word(dev, 0x378, 0x19FA); // 0x0FFA-> 0x19FA. ++ write_nic_word(dev, 0x37A, 0x19FA); // 0x0FFA-> 0x19FA. ++ write_nic_word(dev, 0x37C, 0x00D0); ++ ++ write_nic_byte(dev, 0x061, 0x00); ++ ++ // MAC. ++ write_nic_byte(dev, 0x180, 0x0F); ++ write_nic_byte(dev, 0x183, 0x03); ++ // 061218, lanhsin: for victorh request ++ write_nic_byte(dev, 0x0DA, 0x10); ++ //} ++ ++ // ++ // 061213, rcnjko: ++ // Set MAC.0x24D to 0x00 to prevent cts-to-self Tx/Rx stall symptom. ++ // If we set MAC 0x24D to 0x08, OFDM and CCK will turn off ++ // if not in use, and there is a bug about this action when ++ // we try to send CCK CTS and OFDM data together. ++ // ++ //PlatformEFIOWrite1Byte(Adapter, 0x24D, 0x00); ++ // 061218, lanhsin: for victorh request ++ write_nic_byte(dev, 0x24D, 0x08); ++ ++ // ++ // 061215, rcnjko: ++ // Follow SD3 RTL8185B_87B_MacPhy_Register.doc v0.4. ++ // ++ write_nic_dword(dev, HSSI_PARA, 0x0600321B); ++ // ++ // 061226, rcnjko: ++ // Babble found in HCT 2c_simultaneous test, server with 87B might ++ // receive a packet size about 2xxx bytes. ++ // So, we restrict RMS to 2048 (0x800), while as IC default value is 0xC00. ++ // ++ write_nic_word(dev, RMS, 0x0800); ++ ++ /*****20070321 Resolve HW page bug on system logo test ++ u8 faketemp=read_nic_byte(dev, 0x50);*/ ++ } ++} ++ ++/* this configures registers for beacon tx and enables it via ++ * rtl8180_beacon_tx_enable(). rtl8180_beacon_tx_disable() might ++ * be used to stop beacon transmission ++ */ ++#if 0 ++void rtl8180_start_tx_beacon(struct net_device *dev) ++{ ++ int i; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ u16 word; ++ DMESG("Enabling beacon TX"); ++ //write_nic_byte(dev, 0x42,0xe6);// TCR ++ //rtl8180_init_beacon(dev); ++ //set_nic_txring(dev); ++// rtl8180_prepare_beacon(dev); ++ rtl8180_irq_disable(dev); ++// rtl8180_beacon_tx_enable(dev); ++ rtl8180_set_mode(dev,EPROM_CMD_CONFIG); ++ //write_nic_byte(dev,0x9d,0x20); //DMA Poll ++ //write_nic_word(dev,0x7a,0); ++ //write_nic_word(dev,0x7a,0x8000); ++ ++ ++ word = read_nic_word(dev, BcnItv); ++ word &= ~BcnItv_BcnItv; // clear Bcn_Itv ++ write_nic_word(dev, BcnItv, word); ++ ++ write_nic_word(dev, AtimWnd, ++ read_nic_word(dev, AtimWnd) &~ AtimWnd_AtimWnd); ++ ++ word = read_nic_word(dev, BintrItv); ++ word &= ~BintrItv_BintrItv; ++ ++ //word |= priv->ieee80211->beacon_interval * ++ // ((priv->txbeaconcount > 1)?(priv->txbeaconcount-1):1); ++ // FIXME:FIXME check if correct ^^ worked with 0x3e8; ++ ++ write_nic_word(dev, BintrItv, word); ++ ++ //write_nic_word(dev,0x2e,0xe002); ++ //write_nic_dword(dev,0x30,0xb8c7832e); ++ for(i=0; iieee80211->beacon_cell_ssid[i]); ++ ++// rtl8180_update_msr(dev); ++ ++ ++ //write_nic_byte(dev,CONFIG4,3); /* !!!!!!!!!! */ ++ ++ rtl8180_set_mode(dev, EPROM_CMD_NORMAL); ++ ++ rtl8180_irq_enable(dev); ++ ++ /* VV !!!!!!!!!! VV*/ ++ /* ++ rtl8180_set_mode(dev,EPROM_CMD_CONFIG); ++ write_nic_byte(dev,0x9d,0x00); ++ rtl8180_set_mode(dev,EPROM_CMD_NORMAL); ++*/ ++} ++#endif ++/*************************************************************************** ++ -------------------------------NET STUFF--------------------------- ++***************************************************************************/ ++static struct net_device_stats *rtl8180_stats(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ return &priv->ieee80211->stats; ++} ++ ++int _rtl8180_up(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ //int i; ++ ++ priv->driver_upping = 1; ++ priv->up=1; ++ ++#ifdef LED ++ if(priv->ieee80211->bHwRadioOff == false) ++ priv->ieee80211->ieee80211_led_contorl(dev,LED_CTL_POWER_ON); ++#endif ++ MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_SW); ++ ++ rtl8180_adapter_start(dev); ++ rtl8180_rx_enable(dev); ++ rtl8180_tx_enable(dev); ++//by amy for rate adaptive ++ timer_rate_adaptive((unsigned long)dev); ++//by amy for rate adaptive ++ ++#ifdef SW_ANTE_DIVERSITY ++ if(priv->bSwAntennaDiverity){ ++ //DMESG("SW Antenna Diversity Enable!"); ++ SwAntennaDiversityTimerCallback(dev); ++ } ++#endif ++#ifdef POLLING_METHOD_FOR_RADIO ++ if(priv->polling_timer_on == 0){//add for S3/S4 ++ gpio_change_polling((unsigned long)dev); ++ } ++#endif ++ ++ ieee80211_softmac_start_protocol(priv->ieee80211); ++ ++//by amy for ps ++ watch_dog_adaptive((unsigned long)dev); ++//by amy for ps ++ ++ ieee80211_reset_queue(priv->ieee80211); ++ if(!netif_queue_stopped(dev)) ++ netif_start_queue(dev); ++ else ++ netif_wake_queue(dev); ++ ++#ifndef CONFIG_SOFT_BEACON ++ if(NIC_8187B == priv->card_8187) ++ rtl8187_rx_manage_initiate(dev); ++#endif ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(priv->mshobj && priv->mshobj->ext_patch_rtl8180_up ) ++ priv->mshobj->ext_patch_rtl8180_up(priv->mshobj); ++#endif ++ ++ ++ priv->driver_upping = 0; ++ DMESG("rtl8187_open process complete"); ++ return 0; ++} ++ ++ ++int rtl8180_open(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int ret; ++//changed by lizhaoming for power on/off ++ if(priv->ieee80211->bHwRadioOff == false){ ++ DMESG("rtl8187_open process "); ++ down(&priv->wx_sem); ++ ret = rtl8180_up(dev); ++ up(&priv->wx_sem); ++ return ret; ++ }else{ ++ DMESG("rtl8187_open process failed because radio off"); ++ return -1; ++ } ++ ++} ++ ++ ++int rtl8180_up(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if (priv->up == 1) return -1; ++ ++ return _rtl8180_up(dev); ++} ++ ++ ++int rtl8180_close(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int ret; ++ ++ if (priv->up == 0) return -1; ++ ++ down(&priv->wx_sem); ++ ++ //DMESG("rtl8187_close process"); ++ ret = rtl8180_down(dev); ++#ifdef LED ++ priv->ieee80211->ieee80211_led_contorl(dev,LED_CTL_POWER_OFF); ++#endif ++ up(&priv->wx_sem); ++ ++ return ret; ++ ++} ++ ++int rtl8180_down(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ if (priv->up == 0) return -1; ++ ++ priv->up=0; ++ ++/* FIXME */ ++ if (!netif_queue_stopped(dev)) ++ netif_stop_queue(dev); ++ ++ DMESG("rtl8180_down process"); ++ rtl8180_rtx_disable(dev); ++ rtl8180_irq_disable(dev); ++//by amy for rate adaptive ++ del_timer_sync(&priv->rateadapter_timer); ++ cancel_delayed_work(&priv->ieee80211->rate_adapter_wq); ++//by amy for rate adaptive ++ del_timer_sync(&priv->watch_dog_timer); ++ cancel_delayed_work(&priv->ieee80211->watch_dog_wq); ++ cancel_delayed_work(&priv->ieee80211->hw_dig_wq); ++ cancel_delayed_work(&priv->ieee80211->tx_pw_wq); ++ ++#ifdef SW_ANTE_DIVERSITY ++ del_timer_sync(&priv->SwAntennaDiversityTimer); ++ cancel_delayed_work(&priv->ieee80211->SwAntennaWorkItem); ++#endif ++ ++ ieee80211_softmac_stop_protocol(priv->ieee80211); ++ MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_SW); ++ //amy,081212 ++ memset(&(priv->ieee80211->current_network),0,sizeof(struct ieee80211_network)); ++ return 0; ++} ++ ++bool SetZebraRFPowerState8187B(struct net_device *dev,RT_RF_POWER_STATE eRFPowerState); ++ ++void rtl8180_commit(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ int i; ++ ++ if (priv->up == 0) return ; ++ printk("==========>%s()\n", __FUNCTION__); ++ ++ /* FIXME */ ++ if (!netif_queue_stopped(dev)) ++ netif_stop_queue(dev); ++ ++//by amy for rate adaptive ++ del_timer_sync(&priv->rateadapter_timer); ++ cancel_delayed_work(&priv->ieee80211->rate_adapter_wq); ++//by amy for rate adaptive ++ del_timer_sync(&priv->watch_dog_timer); ++ cancel_delayed_work(&priv->ieee80211->watch_dog_wq); ++ cancel_delayed_work(&priv->ieee80211->hw_dig_wq); ++ cancel_delayed_work(&priv->ieee80211->tx_pw_wq); ++ ++#ifdef SW_ANTE_DIVERSITY ++ del_timer_sync(&priv->SwAntennaDiversityTimer); ++ cancel_delayed_work(&priv->ieee80211->SwAntennaWorkItem); ++#endif ++ ieee80211_softmac_stop_protocol(priv->ieee80211); ++ ++#if 0 ++ if(priv->ieee80211->bHwRadioOff == false){ ++ MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_HW); ++ mdelay(10); ++ MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_HW); ++ } ++#endif ++ ++ rtl8180_irq_disable(dev); ++ rtl8180_rtx_disable(dev); ++ ++ //test pending bug, john 20070815 ++ //initialize tx_pending ++ for(i=0;i<0x10;i++) atomic_set(&(priv->tx_pending[i]), 0); ++ ++ _rtl8180_up(dev); ++ priv->commit = 0; ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void rtl8180_restart(struct work_struct *work) ++{ ++ struct r8180_priv *priv = container_of(work, struct r8180_priv, reset_wq); ++ struct ieee80211_device* ieee = priv->ieee80211;//for commit crash ++ struct net_device *dev = ieee->dev;//for commit crash ++#else ++void rtl8180_restart(struct net_device *dev) ++{ ++ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++#endif ++ ++ down(&priv->wx_sem); ++ ++ rtl8180_commit(dev); ++ ++ up(&priv->wx_sem); ++} ++ ++static void r8180_set_multicast(struct net_device *dev) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ short promisc; ++ ++ //down(&priv->wx_sem); ++ ++ /* FIXME FIXME */ ++ ++ promisc = (dev->flags & IFF_PROMISC) ? 1:0; ++ ++ if (promisc != priv->promisc) ++ // rtl8180_commit(dev); ++ ++ priv->promisc = promisc; ++ ++ //schedule_work(&priv->reset_wq); ++ //up(&priv->wx_sem); ++} ++ ++ ++int r8180_set_mac_adr(struct net_device *dev, void *mac) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ struct sockaddr *addr = mac; ++ ++ down(&priv->wx_sem); ++ ++ memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) ++ schedule_work(&priv->reset_wq); ++#else ++ schedule_task(&priv->reset_wq); ++#endif ++ up(&priv->wx_sem); ++ ++ return 0; ++} ++ ++struct ipw_param { ++ u32 cmd; ++ u8 sta_addr[ETH_ALEN]; ++ union { ++ struct { ++ u8 name; ++ u32 value; ++ } wpa_param; ++ struct { ++ u32 len; ++ u8 reserved[32]; ++ u8 data[0]; ++ } wpa_ie; ++ struct{ ++ u32 command; ++ u32 reason_code; ++ } mlme; ++ struct { ++ u8 alg[16]; ++ u8 set_tx; ++ u32 err; ++ u8 idx; ++ u8 seq[8]; ++ u16 key_len; ++ u8 key[0]; ++ } crypt; ++ ++ } u; ++}; ++ ++ ++/* based on ipw2200 driver */ ++int rtl8180_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ struct iwreq *wrq = (struct iwreq *)rq; ++ int ret=-1; ++ ++#ifdef JOHN_TKIP ++ u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; ++ ++ struct ieee80211_device *ieee = priv->ieee80211; ++ struct ipw_param *ipw = (struct ipw_param *)wrq->u.data.pointer; ++ u32 key[4]; ++ ++#endif ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(priv->mshobj && (priv->ieee80211->iw_mode == priv->ieee80211->iw_ext_mode) && priv->mshobj->ext_patch_rtl8180_ioctl) ++ { ++ // DO NOT put the belowing function in critical section, due to it uses "spin lock" ++ if((ret = priv->mshobj->ext_patch_rtl8180_ioctl(dev, rq, cmd)) != -EOPNOTSUPP) ++ return ret; ++ } ++#endif ++ ++ down(&priv->wx_sem); ++ ++ switch (cmd) { ++ case RTL_IOCTL_WPA_SUPPLICANT: ++#ifdef JOHN_TKIP ++ ++//the following code is specified for ipw driver in wpa_supplicant ++ if( ((u32*)wrq->u.data.pointer)[0]==3 ){ ++ ++ ++ if( ((u32*)wrq->u.data.pointer)[7] && ++ ( ((u32*)wrq->u.data.pointer)[3]==0x504d4343 || ++ ((u32*)wrq->u.data.pointer)[3]==0x50494b54 )) {//50494b54 tkip and 504d4343 ccmp ++ ++ //enable HW security of TKIP and CCMP ++ write_nic_byte(dev, WPA_CONFIG, SCR_TxSecEnable | SCR_RxSecEnable ); ++ ++ //copy key from wpa_supplicant ioctl info ++ key[0] = ((u32*)wrq->u.data.pointer)[12]; ++ key[1] = ((u32*)wrq->u.data.pointer)[13]; ++ key[2] = ((u32*)wrq->u.data.pointer)[14]; ++ key[3] = ((u32*)wrq->u.data.pointer)[15]; ++ switch (ieee->pairwise_key_type){ ++ case KEY_TYPE_TKIP: ++ setKey( dev, ++ 0, //EntryNo ++ ipw->u.crypt.idx, //KeyIndex ++ KEY_TYPE_TKIP, //KeyType ++ (u8*)ieee->ap_mac_addr, //MacAddr ++ 0, //DefaultKey ++ key); //KeyContent ++ break; ++ ++ case KEY_TYPE_CCMP: ++ setKey( dev, ++ 0, //EntryNo ++ ipw->u.crypt.idx, //KeyIndex ++ KEY_TYPE_CCMP, //KeyType ++ (u8*)ieee->ap_mac_addr, //MacAddr ++ 0, //DefaultKey ++ key); //KeyContent ++ break ++; ++ default: ++ printk("error on key_type: %d\n", ieee->pairwise_key_type); ++ break; ++ } ++ } ++ ++ //group key for broadcast ++ if( ((u32*)wrq->u.data.pointer)[9] ) { ++ ++ key[0] = ((u32*)wrq->u.data.pointer)[12]; ++ key[1] = ((u32*)wrq->u.data.pointer)[13]; ++ key[2] = ((u32*)wrq->u.data.pointer)[14]; ++ key[3] = ((u32*)wrq->u.data.pointer)[15]; ++ ++ if( ((u32*)wrq->u.data.pointer)[3]==0x50494b54 ){//50494b54 is the ASCII code of TKIP in reversed order ++ setKey( dev, ++ 1, //EntryNo ++ ipw->u.crypt.idx,//KeyIndex ++ KEY_TYPE_TKIP, //KeyType ++ broadcast_addr, //MacAddr ++ 0, //DefaultKey ++ key); //KeyContent ++ } ++ else if( ((u32*)wrq->u.data.pointer)[3]==0x504d4343 ){//CCMP ++ setKey( dev, ++ 1, //EntryNo ++ ipw->u.crypt.idx,//KeyIndex ++ KEY_TYPE_CCMP, //KeyType ++ broadcast_addr, //MacAddr ++ 0, //DefaultKey ++ key); //KeyContent ++ } ++ else if( ((u32*)wrq->u.data.pointer)[3]==0x656e6f6e ){//none ++ //do nothing ++ } ++ else if( ((u32*)wrq->u.data.pointer)[3]==0x504557 ){//WEP ++ setKey( dev, ++ 1, //EntryNo ++ ipw->u.crypt.idx,//KeyIndex ++ KEY_TYPE_WEP40, //KeyType ++ broadcast_addr, //MacAddr ++ 0, //DefaultKey ++ key); //KeyContent ++ } ++ else printk("undefine group key type: %8x\n", ((u32*)wrq->u.data.pointer)[3]); ++ } ++ ++ } ++#endif /*JOHN_TKIP*/ ++ ++ ++#ifdef JOHN_HWSEC_DEBUG ++ { ++ int i; ++ //john's test 0711 ++ printk("@@ wrq->u pointer = "); ++ for(i=0;iu.data.length;i++){ ++ if(i%10==0) printk("\n"); ++ printk( "%8x|", ((u32*)wrq->u.data.pointer)[i] ); ++ } ++ printk("\n"); ++ } ++#endif /*JOHN_HWSEC_DEBUG*/ ++ ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data); ++ break; ++ ++ default: ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ up(&priv->wx_sem); ++ ++ return ret; ++} ++ ++ ++struct tx_desc { ++ ++#ifdef _LINUX_BYTEORDER_LITTLE_ENDIAN_H ++ ++ ++//dword 0 ++unsigned int tpktsize:12; ++unsigned int rsvd0:3; ++unsigned int no_encrypt:1; ++unsigned int splcp:1; ++unsigned int morefrag:1; ++unsigned int ctsen:1; ++unsigned int rtsrate:4; ++unsigned int rtsen:1; ++unsigned int txrate:4; ++unsigned int last:1; ++unsigned int first:1; ++unsigned int dmaok:1; ++unsigned int own:1; ++ ++//dword 1 ++unsigned short rtsdur; ++unsigned short length:15; ++unsigned short l_ext:1; ++ ++//dword 2 ++unsigned int bufaddr; ++ ++ ++//dword 3 ++unsigned short rxlen:12; ++unsigned short rsvd1:3; ++unsigned short miccal:1; ++unsigned short dur; ++ ++//dword 4 ++unsigned int nextdescaddr; ++ ++//dword 5 ++unsigned char rtsagc; ++unsigned char retrylimit; ++unsigned short rtdb:1; ++unsigned short noacm:1; ++unsigned short pifs:1; ++unsigned short rsvd2:4; ++unsigned short rtsratefallback:4; ++unsigned short ratefallback:5; ++ ++//dword 6 ++unsigned short delaybound; ++unsigned short rsvd3:4; ++unsigned short agc:8; ++unsigned short antenna:1; ++unsigned short spc:2; ++unsigned short rsvd4:1; ++ ++//dword 7 ++unsigned char len_adjust:2; ++unsigned char rsvd5:1; ++unsigned char tpcdesen:1; ++unsigned char tpcpolarity:2; ++unsigned char tpcen:1; ++unsigned char pten:1; ++ ++unsigned char bckey:6; ++unsigned char enbckey:1; ++unsigned char enpmpd:1; ++unsigned short fragqsz; ++ ++ ++#else ++ ++#error "please modify tx_desc to your own\n" ++ ++#endif ++ ++ ++} __attribute__((packed)); ++ ++struct rx_desc_rtl8187b { ++ ++#ifdef _LINUX_BYTEORDER_LITTLE_ENDIAN_H ++ ++//dword 0 ++unsigned int rxlen:12; ++unsigned int icv:1; ++unsigned int crc32:1; ++unsigned int pwrmgt:1; ++unsigned int res:1; ++unsigned int bar:1; ++unsigned int pam:1; ++unsigned int mar:1; ++unsigned int qos:1; ++unsigned int rxrate:4; ++unsigned int trsw:1; ++unsigned int splcp:1; ++unsigned int fovf:1; ++unsigned int dmafail:1; ++unsigned int last:1; ++unsigned int first:1; ++unsigned int eor:1; ++unsigned int own:1; ++ ++ ++//dword 1 ++unsigned int tsftl; ++ ++ ++//dword 2 ++unsigned int tsfth; ++ ++ ++//dword 3 ++unsigned char sq; ++unsigned char rssi:7; ++unsigned char antenna:1; ++ ++unsigned char agc; ++unsigned char decrypted:1; ++unsigned char wakeup:1; ++unsigned char shift:1; ++unsigned char rsvd0:5; ++ ++//dword 4 ++unsigned int num_mcsi:4; ++unsigned int snr_long2end:6; ++unsigned int cfo_bias:6; ++ ++int pwdb_g12:8; ++unsigned int fot:8; ++ ++ ++ ++ ++#else ++ ++#error "please modify tx_desc to your own\n" ++ ++#endif ++ ++}__attribute__((packed)); ++ ++ ++ ++struct rx_desc_rtl8187 { ++ ++#ifdef _LINUX_BYTEORDER_LITTLE_ENDIAN_H ++ ++//dword 0 ++unsigned int rxlen:12; ++unsigned int icv:1; ++unsigned int crc32:1; ++unsigned int pwrmgt:1; ++unsigned int res:1; ++unsigned int bar:1; ++unsigned int pam:1; ++unsigned int mar:1; ++unsigned int qos:1; ++unsigned int rxrate:4; ++unsigned int trsw:1; ++unsigned int splcp:1; ++unsigned int fovf:1; ++unsigned int dmafail:1; ++unsigned int last:1; ++unsigned int first:1; ++unsigned int eor:1; ++unsigned int own:1; ++ ++//dword 1 ++unsigned char sq; ++unsigned char rssi:7; ++unsigned char antenna:1; ++ ++unsigned char agc; ++unsigned char decrypted:1; ++unsigned char wakeup:1; ++unsigned char shift:1; ++unsigned char rsvd0:5; ++ ++//dword 2 ++unsigned int tsftl; ++ ++//dword 3 ++unsigned int tsfth; ++ ++ ++ ++#else ++ ++#error "please modify tx_desc to your own\n" ++ ++#endif ++ ++ ++}__attribute__((packed)); ++ ++ ++ ++union rx_desc { ++ ++struct rx_desc_rtl8187b desc_87b; ++struct rx_desc_rtl8187 desc_87; ++ ++}__attribute__((packed)); ++ ++// ++// Description: ++// Perform signal smoothing for dynamic mechanism. ++// This is different with PerformSignalSmoothing8187 in smoothing fomula. ++// No dramatic adjustion is apply because dynamic mechanism need some degree ++// of correctness. ++// 2007.01.23, by shien chang. ++// ++void PerformUndecoratedSignalSmoothing8187(struct net_device *dev, struct ieee80211_rx_stats *stats) ++{ ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ bool bCckRate = rtl8180_IsWirelessBMode(rtl8180_rate2rate(stats->rate)); ++ ++ if(NIC_8187 == priv->card_8187) { ++ if(priv->UndecoratedSmoothedSS >= 0) { ++ priv->UndecoratedSmoothedSS = ((priv->UndecoratedSmoothedSS * 50) + (stats->signalstrength * 11)) / 60; ++ }else{ ++ priv->UndecoratedSmoothedSS = stats->signalstrength; ++ } ++ } else { ++ // Determin the current packet is CCK rate, by Bruce, 2007-04-12. ++ priv->bCurCCKPkt = bCckRate; ++ ++ // Tesing for SD3 DZ, by Bruce, 2007-04-11. ++ if(priv->UndecoratedSmoothedSS >= 0) { ++ priv->UndecoratedSmoothedSS = ((priv->UndecoratedSmoothedSS * 5) + (stats->signalstrength * 10)) / 6; ++ }else{ ++ priv->UndecoratedSmoothedSS = stats->signalstrength * 10; ++ } ++ ++ // ++ // Bacause the AGC parameter is not exactly correct under high power (AGC saturation), we need to record the RSSI value to be ++ // referenced by DoRxHighPower. It is not necessary to record this value when this packet is sent by OFDM rate. ++ // Advised by SD3 DZ, by Bruce, 2007-04-12. ++ // ++ if(bCckRate){ ++ priv->CurCCKRSSI = stats->signal; ++ }else{ ++ priv->CurCCKRSSI = 0; ++ } ++ } ++ //printk("Sommthing SignalSterngth (%d) => UndecoratedSmoothedSS (%d)\n", stats->signalstrength, priv->UndecoratedSmoothedSS); ++} ++ ++#ifdef THOMAS_SKB ++void rtl8180_irq_rx_tasklet(struct r8180_priv *priv) ++{ ++ int status,len,flen; ++ ++#ifdef SW_ANTE_DIVERSITY ++ u8 Antenna = 0; ++#endif ++ u32 SignalStrength = 0; ++ u32 quality = 0; ++ bool bCckRate = false; ++ char RX_PWDB = 0; ++ long RecvSignalPower=0; ++ struct sk_buff *skb; ++ struct sk_buff *skb2;//skb for check out of memory ++ union rx_desc *desc; ++ //struct urb *rx_urb = priv->rxurb_task; ++ struct ieee80211_hdr *hdr;//by amy ++ u16 fc,type; ++ u8 bHwError=0,bCRC=0,bICV=0; ++ long SignalStrengthIndex = 0; ++ struct ieee80211_rx_stats stats = { ++ .signal = 0, ++ .noise = -98, ++ .rate = 0, ++ //.mac_time = jiffies, ++ .freq = IEEE80211_24GHZ_BAND, ++ }; ++ ++ int *prx_inx=&priv->rx_inx; ++ struct urb *rx_urb=priv->rx_urb[*prx_inx]; //changed by jackson ++ struct net_device *dev = (struct net_device*)rx_urb->context; ++ //DMESG("=====>RX %x ",rx_urb->status); ++ ++ skb = priv->pp_rxskb[*prx_inx]; ++ status = rx_urb->status; ++ skb2 = dev_alloc_skb(RX_URB_SIZE); ++ ++ if (skb2 == NULL){ ++ printk(KERN_ALERT "No Skb For RX!/n"); ++ //rx_urb->transfer_buffer = skb->data; ++ //priv->pp_rxskb[*prx_inx] = skb; ++ } else { ++ ++ if(status == 0) ++ { ++ if(NIC_8187B == priv->card_8187) ++ { ++ stats.nic_type = NIC_8187B; ++ len = rx_urb->actual_length; ++ len -= sizeof (struct rx_desc_rtl8187b); ++ desc = (union rx_desc *)(rx_urb->transfer_buffer + len); ++ flen = desc->desc_87b.rxlen ; ++ ++ if( flen <= rx_urb->actual_length){ ++#if 1 ++#ifdef SW_ANTE_DIVERSITY ++ Antenna = desc->desc_87b.antenna; ++#endif ++ stats.mac_time[0] = desc->desc_87b.tsftl; ++ stats.mac_time[1] = desc->desc_87b.tsfth; ++ ++ stats.signal = desc->desc_87b.rssi; ++ //stats.noise = desc->desc_87b.sq; ++ quality = desc->desc_87b.sq; ++ stats.rate = desc->desc_87b.rxrate; ++ bCckRate = rtl8180_IsWirelessBMode(rtl8180_rate2rate(stats.rate)); ++ ++ if(!bCckRate) { // OFDM rate. ++ if(desc->desc_87b.pwdb_g12 < -106) ++ SignalStrength = 0; ++ else ++ SignalStrength = desc->desc_87b.pwdb_g12 + 106; ++ RX_PWDB = (desc->desc_87b.pwdb_g12)/2 -42; ++ } else { // CCK rate. ++ if(desc->desc_87b.agc> 174) ++ SignalStrength = 0; ++ else ++ SignalStrength = 174 - desc->desc_87b.agc; ++ RX_PWDB = ((desc->desc_87b.agc)/2)*(-1) - 8; ++ } ++ ++ //lzm mod 081028 based on windows driver ++ //compensate SignalStrength when switch TR to SW controled ++ if(priv->TrSwitchState == TR_SW_TX) { ++ SignalStrength = SignalStrength + 54; ++ RX_PWDB = RX_PWDB + 27; ++ } ++ ++ if(SignalStrength > 100) ++ SignalStrength = 100; ++ SignalStrength = (SignalStrength * 70) / 100 + 30; ++ ++ if(SignalStrength > 50) ++ SignalStrength = SignalStrength + 10; ++ if(SignalStrength > 100) ++ SignalStrength = 100; ++ ++ RecvSignalPower = RX_PWDB; ++ //printk("SignalStrength = %d \n",SignalStrength); ++ bHwError = (desc->desc_87b.fovf | desc->desc_87b.icv | desc->desc_87b.crc32); ++ bCRC = desc->desc_87b.crc32; ++ bICV = desc->desc_87b.icv; ++ priv->wstats.qual.level = (u8)SignalStrength; ++ ++ if(!bCckRate){ ++ if (quality > 127) ++ quality = 0; ++ else if (quality <27) ++ quality = 100; ++ else ++ quality = 127 - quality; ++ } else { ++ if(quality > 64) ++ quality = 0; ++ else ++ quality = ((64-quality)*100)/64; ++ } ++ ++ ++ priv ->wstats.qual.qual = quality; ++ priv->wstats.qual.noise = 100 - priv ->wstats.qual.qual; ++ ++ stats.signalstrength = (u8)SignalStrength; ++ stats.signal = (u8)quality; ++ stats.noise = desc->desc_87b.snr_long2end; ++ ++ skb_put(skb,flen-4); ++ ++ priv->stats.rxok++; ++ //by amy ++ hdr = (struct ieee80211_hdr *)skb->data; ++ fc = le16_to_cpu(hdr->frame_ctl); ++ type = WLAN_FC_GET_TYPE(fc); ++ ++ if((IEEE80211_FTYPE_CTL != type) && ++ (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS )? hdr->addr2 : hdr->addr3)) && (!bHwError) && (!bCRC)&& (!bICV)) ++ { ++ // Perform signal smoothing for dynamic mechanism on demand. ++ // This is different with PerformSignalSmoothing8187 in smoothing fomula. ++ // No dramatic adjustion is apply because dynamic mechanism need some degree ++ // of correctness. 2007.01.23, by shien chang. ++ PerformUndecoratedSignalSmoothing8187(dev, &stats); ++ ++ //Update signal strength and realted into private RxStats for UI query. ++ SignalStrengthIndex = NetgearSignalStrengthTranslate(priv->LastSignalStrengthInPercent, priv->wstats.qual.level); ++ priv->LastSignalStrengthInPercent = SignalStrengthIndex; ++ priv->SignalStrength = TranslateToDbm8187((u8)SignalStrengthIndex); ++ priv->SignalQuality = (priv->SignalQuality*5+quality+5)/6; ++ priv->RecvSignalPower = (priv->RecvSignalPower * 5 + RecvSignalPower - 1) / 6; ++#ifdef SW_ANTE_DIVERSITY ++ priv->LastRxPktAntenna = Antenna ? 1:0; ++ SwAntennaDiversityRxOk8185(dev, SignalStrength); ++#endif ++ } ++ //by amy ++#endif ++ if(!ieee80211_rx(priv->ieee80211,skb, &stats)) { ++ dev_kfree_skb_any(skb); ++ } ++ }else { ++ priv->stats.rxurberr++; ++ printk("URB Error flen:%d actual_length:%d\n", flen , rx_urb->actual_length); ++ dev_kfree_skb_any(skb); ++ } ++ } else { ++ stats.nic_type = NIC_8187; ++ len = rx_urb->actual_length; ++ len -= sizeof (struct rx_desc_rtl8187); ++ desc = (union rx_desc *)(rx_urb->transfer_buffer + len); ++ flen = desc->desc_87.rxlen ; ++ ++ if(flen <= rx_urb->actual_length){ ++ stats.signal = desc->desc_87.rssi; ++ stats.noise = desc->desc_87.sq; ++ stats.rate = desc->desc_87.rxrate; ++ stats.mac_time[0] = desc->desc_87.tsftl; ++ stats.mac_time[1] = desc->desc_87.tsfth; ++ SignalStrength = (desc->desc_87.agc&0xfe) >> 1; ++ if( ((stats.rate <= 22) && (stats.rate != 12) && (stats.rate != 18)) || (stats.rate == 44) )//need to translate to real rate here ++ bCckRate= TRUE; ++ if (!bCckRate) ++ { ++ if (SignalStrength > 90) SignalStrength = 90; ++ else if (SignalStrength < 25) SignalStrength = 25; ++ SignalStrength = ((90 - SignalStrength)*100)/65; ++ } ++ else ++ { ++ if (SignalStrength >95) SignalStrength = 95; ++ else if (SignalStrength < 30) SignalStrength = 30; ++ SignalStrength = ((95 - SignalStrength)*100)/65; ++ } ++ stats.signalstrength = (u8)SignalStrength; ++ ++ skb_put(skb,flen-4); ++ ++ priv->stats.rxok++; ++ ++ if(!ieee80211_rx(priv->ieee80211,skb, &stats)) ++ dev_kfree_skb_any(skb); ++ ++ ++ }else { ++ priv->stats.rxurberr++; ++ printk("URB Error flen:%d actual_length:%d\n", flen , rx_urb->actual_length); ++ dev_kfree_skb_any(skb); ++ } ++ } ++ }else{ ++ ++ //printk("RX Status Error!\n"); ++ priv->stats.rxstaterr++; ++ priv->ieee80211->stats.rx_errors++; ++ dev_kfree_skb_any(skb); ++ ++ } ++ ++ rx_urb->transfer_buffer = skb2->data; ++ ++ priv->pp_rxskb[*prx_inx] = skb2; ++ } ++ ++ if(status != -ENOENT ){ ++ rtl8187_rx_urbsubmit(dev,rx_urb); ++ } else { ++ priv->pp_rxskb[*prx_inx] = NULL; ++ dev_kfree_skb_any(skb2); ++ //printk("RX process %d aborted due to explicit shutdown (%x)(%d)\n ", *prx_inx, status, status); ++ } ++ ++ if (*prx_inx == (MAX_RX_URB -1)) ++ *prx_inx = 0; ++ else ++ *prx_inx = *prx_inx + 1; ++} ++#endif ++ ++#ifdef THOMAS_TASKLET ++void rtl8180_irq_rx_tasklet_new(struct r8180_priv *priv){ ++ unsigned long flags; ++ while( atomic_read( &priv->irt_counter ) ){ ++ spin_lock_irqsave(&priv->irq_lock,flags);//added by thomas ++ rtl8180_irq_rx_tasklet(priv); ++ spin_unlock_irqrestore(&priv->irq_lock,flags);//added by thomas ++ if(atomic_read(&priv->irt_counter) >= 1) ++ atomic_dec( &priv->irt_counter ); ++ } ++} ++#endif ++/**************************************************************************** ++ ---------------------------- USB_STUFF--------------------------- ++*****************************************************************************/ ++ ++static const struct net_device_ops rtl8187_netdev_ops = { ++ .ndo_open = rtl8180_open, ++ .ndo_stop = rtl8180_close, ++ .ndo_tx_timeout = tx_timeout, ++ .ndo_do_ioctl = rtl8180_ioctl, ++ .ndo_set_multicast_list = r8180_set_multicast, ++ .ndo_set_mac_address = r8180_set_mac_adr, ++ .ndo_validate_addr = eth_validate_addr, ++ .ndo_change_mtu = eth_change_mtu, ++ .ndo_start_xmit = ieee80211_xmit, ++ .ndo_get_stats = rtl8180_stats, ++}; ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++static int __devinit rtl8187_usb_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++#else ++static void * __devinit rtl8187_usb_probe(struct usb_device *udev, ++ unsigned int ifnum, ++ const struct usb_device_id *id) ++#endif ++{ ++ struct net_device *dev = NULL; ++ struct r8180_priv *priv= NULL; ++ ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ struct usb_device *udev = interface_to_usbdev(intf); ++#endif ++ ++ dev = alloc_ieee80211(sizeof(struct r8180_priv)); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ++ SET_MODULE_OWNER(dev); ++#endif ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ usb_set_intfdata(intf, dev); ++ SET_NETDEV_DEV(dev, &intf->dev); ++#endif ++ priv = ieee80211_priv(dev); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ priv->ieee80211 = netdev_priv(dev); ++#else ++ priv->ieee80211 = (struct net_device *)dev->priv; ++#endif ++ priv->udev=udev; ++#ifdef CPU_64BIT ++ priv->usb_buf = kmalloc(0x200, GFP_KERNEL); ++ priv->usb_pool = dma_pool_create("rtl8187b", NULL, 64, 64, 0); ++#endif ++//lzm add for write time out test ++#ifdef DEBUG_RW_REGISTER ++ { ++ int reg_index = 0; ++ for(reg_index = 0; reg_index <= 199; reg_index++) ++ { ++ priv->write_read_registers[reg_index].address = 0; ++ priv->write_read_registers[reg_index].content = 0; ++ priv->write_read_registers[reg_index].flag = 0; ++ } ++ priv->write_read_register_index = 0; ++ } ++#endif ++ //init netdev_ops, added by falcon.... ++ dev->netdev_ops = &rtl8187_netdev_ops; ++ ++ dev->wireless_handlers = &r8180_wx_handlers_def; ++#if WIRELESS_EXT >= 12 ++#if WIRELESS_EXT < 17 ++ dev->get_wireless_stats = r8180_get_wireless_stats; ++#endif ++ dev->wireless_handlers = (struct iw_handler_def *) &r8180_wx_handlers_def; ++#endif ++ ++ dev->type=ARPHRD_ETHER; ++ dev->watchdog_timeo = HZ*3; //modified by john, 0805 ++ ++ if (dev_alloc_name(dev, ifname) < 0){ ++ DMESG("Oops: devname already taken! Trying wlan%%d...\n"); ++ ifname = "wlan%d"; ++ dev_alloc_name(dev, ifname); ++ } ++ ++ if(rtl8180_init(dev)!=0){ ++ DMESG("Initialization failed"); ++ goto fail; ++ } ++ ++ netif_carrier_off(dev); ++ netif_stop_queue(dev); ++ ++ register_netdev(dev); ++ ++ rtl8180_proc_init_one(dev); ++ ++//by lizhaoming for Radio power on/off ++#ifdef POLLING_METHOD_FOR_RADIO ++ if(priv->polling_timer_on == 0){//add for S3/S4 ++ gpio_change_polling((unsigned long)dev); ++ } ++#endif ++ ++ DMESG("Driver probe completed"); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ++ return dev; ++#else ++ return 0; ++#endif ++ ++ ++fail: ++ free_ieee80211(dev); ++ ++ DMESG("wlan driver load failed\n"); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ++ return NULL; ++#else ++ return -ENODEV; ++#endif ++ ++} ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++static void __devexit rtl8187_usb_disconnect(struct usb_interface *intf) ++#else ++static void __devexit rtl8187_usb_disconnect(struct usb_device *udev, void *ptr) ++#endif ++{ ++ struct r8180_priv *priv = NULL; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ struct net_device *dev = usb_get_intfdata(intf); ++#else ++ struct net_device *dev = (struct net_device *)ptr; ++#endif ++ if(dev){ ++ unregister_netdev(dev); ++ ++ priv=ieee80211_priv(dev); ++ ++//add for RF power on power off by lizhaoming 080512 ++#ifdef POLLING_METHOD_FOR_RADIO ++ del_timer_sync(&priv->gpio_polling_timer); ++ cancel_delayed_work(&priv->ieee80211->GPIOChangeRFWorkItem); ++ priv->polling_timer_on = 0;//add for S3/S4 ++#endif ++ MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_SW); ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ if(priv && priv->mshobj) ++ { ++ if(priv->mshobj->ext_patch_remove_proc) ++ priv->mshobj->ext_patch_remove_proc(priv); ++ priv->ieee80211->ext_patch_ieee80211_start_protocol = 0; ++ priv->ieee80211->ext_patch_ieee80211_stop_protocol = 0; ++ priv->ieee80211->ext_patch_ieee80211_probe_req_1 = 0; ++ priv->ieee80211->ext_patch_ieee80211_probe_req_2 = 0; ++ priv->ieee80211->ext_patch_ieee80211_association_req_1 = 0; ++ priv->ieee80211->ext_patch_ieee80211_association_req_2 = 0; ++ priv->ieee80211->ext_patch_ieee80211_assoc_resp_by_net_1 = 0; ++ priv->ieee80211->ext_patch_ieee80211_assoc_resp_by_net_2 = 0; ++ priv->ieee80211->ext_patch_ieee80211_rx_frame_softmac_on_auth =0; ++ priv->ieee80211->ext_patch_ieee80211_rx_frame_softmac_on_deauth =0; ++ priv->ieee80211->ext_patch_ieee80211_rx_frame_softmac_on_assoc_req = 0; ++ priv->ieee80211->ext_patch_ieee80211_rx_frame_softmac_on_assoc_rsp = 0; ++ priv->ieee80211->ext_patch_ieee80211_ext_stop_scan_wq_set_channel = 0; ++ priv->ieee80211->ext_patch_ieee80211_process_probe_response_1 = 0; ++ priv->ieee80211->ext_patch_ieee80211_rx_mgt_on_probe_req = 0; ++ priv->ieee80211->ext_patch_ieee80211_rx_mgt_update_expire = 0; ++ priv->ieee80211->ext_patch_ieee80211_rx_on_rx = 0; ++ priv->ieee80211->ext_patch_get_beacon_get_probersp = 0; ++ priv->ieee80211->ext_patch_ieee80211_xmit = 0; ++ priv->ieee80211->ext_patch_ieee80211_rx_frame_get_hdrlen = 0; ++ priv->ieee80211->ext_patch_ieee80211_rx_is_valid_framectl = 0; ++ priv->ieee80211->ext_patch_ieee80211_rx_process_dataframe = 0; ++ // priv->ieee80211->ext_patch_is_duplicate_packet = 0; ++ priv->ieee80211->ext_patch_ieee80211_softmac_xmit_get_rate = 0; ++ free_mshobj(&priv->mshobj); ++ } ++#endif // _RTL8187_EXT_PATCH_ ++ ++ rtl8180_proc_remove_one(dev); ++ ++ rtl8180_down(dev); ++ priv->rf_close(dev); ++ ++ //rtl8180_rtx_disable(dev); ++ rtl8187_usb_deleteendpoints(dev); ++#ifdef LED ++ DeInitSwLeds(dev); ++#endif ++ rtl8180_irq_disable(dev); ++ rtl8180_reset(dev); ++ mdelay(10); ++ ++ } ++ ++#ifdef CPU_64BIT ++ if(priv->usb_buf) ++ kfree(priv->usb_buf); ++ if(priv->usb_pool) { ++ dma_pool_destroy(priv->usb_pool); ++ priv->usb_pool = NULL; ++ } ++#endif ++ free_ieee80211(dev); ++ DMESG("wlan driver removed"); ++} ++ ++/* fun with the built-in ieee80211 stack... */ ++extern int ieee80211_crypto_init(void); ++extern void ieee80211_crypto_deinit(void); ++extern int ieee80211_crypto_tkip_init(void); ++extern void ieee80211_crypto_tkip_exit(void); ++extern int ieee80211_crypto_ccmp_init(void); ++extern void ieee80211_crypto_ccmp_exit(void); ++extern int ieee80211_crypto_wep_init(void); ++extern void ieee80211_crypto_wep_exit(void); ++ ++static int __init rtl8187_usb_module_init(void) ++{ ++ int ret; ++ ++ ret = ieee80211_crypto_init(); ++ if (ret) { ++ printk(KERN_ERR "ieee80211_crypto_init() failed %d\n", ret); ++ return ret; ++ } ++ ret = ieee80211_crypto_tkip_init(); ++ if (ret) { ++ printk(KERN_ERR "ieee80211_crypto_tkip_init() failed %d\n", ret); ++ return ret; ++ } ++ ret = ieee80211_crypto_ccmp_init(); ++ if (ret) { ++ printk(KERN_ERR "ieee80211_crypto_ccmp_init() failed %d\n", ret); ++ return ret; ++ } ++ ret = ieee80211_crypto_wep_init(); ++ if (ret) { ++ printk(KERN_ERR "ieee80211_crypto_wep_init() failed %d\n", ret); ++ return ret; ++ } ++ ++ printk("\nLinux kernel driver for RTL8187/RTL8187B based WLAN cards\n"); ++ printk("Copyright (c) 2004-2008, Realsil Wlan\n"); ++ DMESG("Initializing module"); ++ DMESG("Wireless extensions version %d", WIRELESS_EXT); ++ rtl8180_proc_module_init(); ++ return usb_register(&rtl8187_usb_driver); ++} ++ ++ ++static void __exit rtl8187_usb_module_exit(void) ++{ ++ usb_deregister(&rtl8187_usb_driver); ++ rtl8180_proc_module_remove(); ++ ieee80211_crypto_tkip_exit(); ++ ieee80211_crypto_ccmp_exit(); ++ ieee80211_crypto_wep_exit(); ++ ieee80211_crypto_deinit(); ++ ++ DMESG("Exiting\n"); ++} ++ ++ ++void rtl8180_try_wake_queue(struct net_device *dev, int pri) ++{ ++ unsigned long flags; ++ short enough_desc; ++ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); ++ ++ spin_lock_irqsave(&priv->tx_lock,flags); ++ enough_desc = check_nic_enought_desc(dev,pri); ++ spin_unlock_irqrestore(&priv->tx_lock,flags); ++ ++ if(enough_desc) ++ ieee80211_wake_queue(priv->ieee80211); ++} ++ ++#ifdef JOHN_HWSEC ++void EnableHWSecurityConfig8187(struct net_device *dev) ++{ ++ u8 SECR_value = 0x0; ++ SECR_value = SCR_TxSecEnable | SCR_RxSecEnable; ++ { ++ write_nic_byte(dev, WPA_CONFIG, 0x7);//SECR_value | SCR_UseDK ); ++ } ++} ++ ++void setKey(struct net_device *dev, ++ u8 EntryNo, ++ u8 KeyIndex, ++ u16 KeyType, ++ u8 *MacAddr, ++ u8 DefaultKey, ++ u32 *KeyContent ) ++{ ++ u32 TargetCommand = 0; ++ u32 TargetContent = 0; ++ u16 usConfig = 0; ++ int i; ++ usConfig |= BIT15 | (KeyType<<2) | (DefaultKey<<5) | KeyIndex; ++ ++ ++ for(i=0 ; i<6 ; i++){ ++ TargetCommand = i+6*EntryNo; ++ TargetCommand |= BIT31|BIT16; ++ ++ if(i==0){//MAC|Config ++ TargetContent = (u32)(*(MacAddr+0)) << 16| ++ (u32)(*(MacAddr+1)) << 24| ++ (u32)usConfig; ++ ++ write_nic_dword(dev, WCAMI, TargetContent); ++ write_nic_dword(dev, RWCAM, TargetCommand); ++ //printk("setkey cam =%8x\n", read_cam(dev, i+6*EntryNo)); ++ } else if(i==1){//MAC ++ TargetContent = (u32)(*(MacAddr+2)) | ++ (u32)(*(MacAddr+3)) << 8| ++ (u32)(*(MacAddr+4)) << 16| ++ (u32)(*(MacAddr+5)) << 24; ++ write_nic_dword(dev, WCAMI, TargetContent); ++ write_nic_dword(dev, RWCAM, TargetCommand); ++ } else { //Key Material ++ write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)) ); ++ write_nic_dword(dev, RWCAM, TargetCommand); ++ } ++ } ++ ++} ++#endif ++ ++/**************************************************************************** ++ --------------------------- RF power on/power off ----------------- ++*****************************************************************************/ ++ ++#ifdef POLLING_METHOD_FOR_RADIO ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) ++void GPIOChangeRFWorkItemCallBack(struct work_struct *work) ++{ ++ //struct delayed_work *dwork = container_of(work, struct delayed_work, work); ++ struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, GPIOChangeRFWorkItem.work); ++ struct net_device *dev = ieee->dev; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++#else ++void GPIOChangeRFWorkItemCallBack(struct ieee80211_device *ieee) ++{ ++ struct net_device *dev = ieee->dev; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++#endif ++ ++ //u16 tmp2byte; ++ u8 tmp1byte; ++ //u8 btPSR; ++ //u8 btConfig0; ++ RT_RF_POWER_STATE eRfPowerStateToSet; ++ bool bActuallySet=false; ++ ++ char *argv[3]; ++ static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh"; ++ static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL}; ++ ++#if 0 ++ if(priv->up == 0)//driver stopped ++ { ++ printk("\nDo nothing..."); ++ goto out; ++ } ++ else ++#endif ++ { ++ // We should turn off LED before polling FF51[4]. ++ ++ //Turn off LED. ++ //btPSR = read_nic_byte(dev, PSR); ++ //write_nic_byte(dev, PSR, (btPSR & ~BIT3)); ++ ++ //It need to delay 4us suggested by Jong, 2008-01-16 ++ //udelay(4); ++ ++ //HW radio On/Off according to the value of FF51[4](config0) ++ //btConfig0 = btPSR = read_nic_byte(dev, CONFIG0); ++ ++ //Turn on LED. ++ //write_nic_byte(dev, PSR, btPSR| BIT3); ++ ++ //eRfPowerStateToSet = (btConfig0 & BIT4) ? eRfOn : eRfOff; ++ ++ // Get RF power state to set. ++ //if Driver isn't stopped, we poll GPIO1 ++ ++ //set 0x91 B1= 0 // 1: for output enable; 0: otherwise. ++ // (William says) Note that, it will cause unstable if we set output enable 1 but not to write it. Annie, 2005-12-12. ++ tmp1byte = read_nic_byte(dev,GPE); ++ if(priv->EEPROMSelectNewGPIO == true) ++ tmp1byte &= ~BIT2;//for toshiba new GPIO use bit2 ++ else ++ tmp1byte &= ~BIT1; ++ ++ write_nic_byte(dev,GPE,tmp1byte); ++ ++ //read 0x92 B1(read GPIO1) ++ tmp1byte = read_nic_byte(dev,GPI); ++ ++ //turn on or trun off RF according to the value of GPIO1 ++ if(priv->EEPROMSelectNewGPIO == true) ++ eRfPowerStateToSet = (tmp1byte&BIT2) ? eRfOn : eRfOff; ++ else ++ eRfPowerStateToSet = (tmp1byte&BIT1) ? eRfOn : eRfOff; ++ ++ if((priv->ieee80211->bHwRadioOff == true) && (eRfPowerStateToSet == eRfOn)){ ++ priv->ieee80211->bHwRadioOff = false; ++ bActuallySet = true; ++ }else if((priv->ieee80211->bHwRadioOff == false) && (eRfPowerStateToSet == eRfOff)){ ++ priv->ieee80211->bHwRadioOff = true; ++ bActuallySet = true; ++ } ++ ++ //if(priv->wlan_first_up_flag1 == 0){ ++ // bActuallySet = true; ++ // priv->wlan_first_up_flag1 = 1; ++ //} ++ ++ if(bActuallySet) ++ { ++ //printk("GPIO1:%x,eRfPowerStateToSet: %x, bHwRadioOff:%x\n", ++ // tmp1byte,eRfPowerStateToSet,priv->ieee80211->bHwRadioOff); ++ ++ //GPIO Polling Methord Made Radio On/Off ++ DMESG("GPIO Polling Methord Will Turn Radio %s", ++ (priv->ieee80211->bHwRadioOff == true) ? "Off" : "On"); ++ ++#ifdef LED //by lizhaoming ++ if(priv->ieee80211->bHwRadioOff == true){ ++ priv->ieee80211->ieee80211_led_contorl(dev,LED_CTL_POWER_OFF); ++ }else{ ++ if(priv->up == 1){ ++ priv->ieee80211->ieee80211_led_contorl(dev,LED_CTL_POWER_ON); ++ } ++ } ++#endif ++ ++ MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW); ++ ++ /* To update the UI status for Power status changed */ ++ if(priv->ieee80211->bHwRadioOff == true) ++ argv[1] = "RFOFF"; ++ else{ ++ //if(priv->eInactivePowerState != eRfOff) ++ argv[1] = "RFON"; ++ //else ++ // argv[1] = "RFOFF"; ++ } ++ argv[0] = RadioPowerPath; ++ argv[2] = NULL; ++ ++ call_usermodehelper(RadioPowerPath,argv,envp,1); ++ } ++ ++ } ++} ++void gpio_change_polling(unsigned long data) ++{ ++ struct r8180_priv* priv = ieee80211_priv((struct net_device *)data); ++ //struct net_device* dev = (struct net_device*)data; ++ ++ priv->polling_timer_on = 1;//add for S3/S4 ++ ++ if(priv->driver_upping == 0){ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++ queue_delayed_work(priv->ieee80211->wq,&priv->ieee80211->GPIOChangeRFWorkItem,0); ++#else ++ queue_work(priv->ieee80211->wq,&priv->ieee80211->GPIOChangeRFWorkItem); ++#endif ++ } ++ ++ mod_timer(&priv->gpio_polling_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME)); ++} ++#endif ++ ++/*************************************************************************** ++ ------------------- module init / exit stubs ---------------- ++****************************************************************************/ ++module_init(rtl8187_usb_module_init); ++module_exit(rtl8187_usb_module_exit); +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8187.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8187.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8187.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8187.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,816 @@ ++/* ++ This is part of rtl8187 OpenSource driver. ++ Copyright (C) Andrea Merello 2004-2005 ++ Released under the terms of GPL (General Public Licence) ++ ++ Parts of this driver are based on the GPL part of the ++ official realtek driver ++ ++ Parts of this driver are based on the rtl8180 driver skeleton ++ from Patric Schenke & Andres Salomon ++ ++ Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver ++ ++ We want to tanks the Authors of those projects and the Ndiswrapper ++ project Authors. ++*/ ++ ++#ifndef R8180H ++#define R8180H ++ ++ ++#define RTL8187_MODULE_NAME "rtl8187" ++#define DMESG(x,a...) printk(KERN_INFO RTL8187_MODULE_NAME ": " x "\n", ## a) ++#define DMESGW(x,a...) printk(KERN_WARNING RTL8187_MODULE_NAME ": WW:" x "\n", ## a) ++#define DMESGE(x,a...) printk(KERN_WARNING RTL8187_MODULE_NAME ": EE:" x "\n", ## a) ++ ++#include ++#include ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++//#include ++#include ++#include ++#include ++#include //for rtnl_lock() ++#include ++#include ++#include // Necessary because we use the proc fs ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) ++#include ++#endif ++#include "ieee80211/ieee80211.h" ++#ifdef _RTL8187_EXT_PATCH_ ++#include "msh_class.h" ++#endif ++#ifdef LED ++#include "r8187_led.h" ++#endif ++ ++//added for HW security, john.0629 ++#define FALSE 0 ++#define TRUE 1 ++#define MAX_KEY_LEN 61 ++#define KEY_BUF_SIZE 5 ++ ++#define BIT0 0x00000001 ++#define BIT1 0x00000002 ++#define BIT2 0x00000004 ++#define BIT3 0x00000008 ++#define BIT4 0x00000010 ++#define BIT5 0x00000020 ++#define BIT6 0x00000040 ++#define BIT7 0x00000080 ++#define BIT8 0x00000100 ++#define BIT9 0x00000200 ++#define BIT10 0x00000400 ++#define BIT11 0x00000800 ++#define BIT12 0x00001000 ++#define BIT13 0x00002000 ++#define BIT14 0x00004000 ++#define BIT15 0x00008000 ++#define BIT16 0x00010000 ++#define BIT17 0x00020000 ++#define BIT18 0x00040000 ++#define BIT19 0x00080000 ++#define BIT20 0x00100000 ++#define BIT21 0x00200000 ++#define BIT22 0x00400000 ++#define BIT23 0x00800000 ++#define BIT24 0x01000000 ++#define BIT25 0x02000000 ++#define BIT26 0x04000000 ++#define BIT27 0x08000000 ++#define BIT28 0x10000000 ++#define BIT29 0x20000000 ++#define BIT30 0x40000000 ++#define BIT31 0x80000000 ++ ++//8187B Security ++#define RWCAM 0xA0 // Software read/write CAM config ++#define WCAMI 0xA4 // Software write CAM input content ++#define RCAMO 0xA8 // Output value from CAM according to 0xa0 setting ++#define DCAM 0xAC // Debug CAM Interface ++#define SECR 0xB0 // Security configuration register ++#define AESMSK_FC 0xB2 // AES Mask register for frame control (0xB2~0xB3). Added by Annie, 2006-03-06. ++#define AESMSK_SC 0x1FC // AES Mask for Sequence Control (0x1FC~0X1FD). Added by Annie, 2006-03-06. ++#define AESMSK_QC 0x1CE // AES Mask register for QoS Control when computing AES MIC, default = 0x000F. (2 bytes) ++ ++#define AESMSK_FC_DEFAULT 0xC78F // default value of AES MASK for Frame Control Field. (2 bytes) ++#define AESMSK_SC_DEFAULT 0x000F // default value of AES MASK for Sequence Control Field. (2 bytes) ++#define AESMSK_QC_DEFAULT 0x000F // default value of AES MASK for QoS Control Field. (2 bytes) ++ ++#define CAM_CONTENT_COUNT 6 ++#define CFG_DEFAULT_KEY BIT5 ++#define CFG_VALID BIT15 ++ ++//---------------------------------------------------------------------------- ++// 8187B WPA Config Register (offset 0xb0, 1 byte) ++//---------------------------------------------------------------------------- ++#define SCR_UseDK 0x01 ++#define SCR_TxSecEnable 0x02 ++#define SCR_RxSecEnable 0x04 ++ ++//---------------------------------------------------------------------------- ++// 8187B CAM Config Setting (offset 0xb0, 1 byte) ++//---------------------------------------------------------------------------- ++#define CAM_VALID 0x8000 ++#define CAM_NOTVALID 0x0000 ++#define CAM_USEDK 0x0020 ++ ++ ++#define CAM_NONE 0x0 ++#define CAM_WEP40 0x01 ++#define CAM_TKIP 0x02 ++#define CAM_AES 0x04 ++#define CAM_WEP104 0x05 ++ ++ ++//#define CAM_SIZE 16 ++#define TOTAL_CAM_ENTRY 16 ++#define CAM_ENTRY_LEN_IN_DW 6 // 6, unit: in u4byte. Added by Annie, 2006-05-25. ++#define CAM_ENTRY_LEN_IN_BYTE (CAM_ENTRY_LEN_IN_DW*sizeof(u4Byte)) // 24, unit: in u1byte. Added by Annie, 2006-05-25. ++ ++#define CAM_CONFIG_USEDK 1 ++#define CAM_CONFIG_NO_USEDK 0 ++ ++#define CAM_WRITE 0x00010000 ++#define CAM_READ 0x00000000 ++#define CAM_POLLINIG 0x80000000 ++ ++//================================================================= ++//================================================================= ++ ++#define EPROM_93c46 0 ++#define EPROM_93c56 1 ++ ++#define DEFAULT_FRAG_THRESHOLD 2342U ++#define MIN_FRAG_THRESHOLD 256U ++#define DEFAULT_BEACONINTERVAL 0x64U ++#define DEFAULT_BEACON_ESSID "Rtl8187" ++ ++#define DEFAULT_SSID "" ++#define DEFAULT_RETRY_RTS 7 ++#define DEFAULT_RETRY_DATA 7 ++#define PRISM_HDR_SIZE 64 ++ ++typedef enum _WIRELESS_MODE { ++ WIRELESS_MODE_UNKNOWN = 0x00, ++ WIRELESS_MODE_A = 0x01, ++ WIRELESS_MODE_B = 0x02, ++ WIRELESS_MODE_G = 0x04, ++ WIRELESS_MODE_AUTO = 0x08, ++} WIRELESS_MODE; ++ ++typedef enum _TR_SWITCH_STATE{ ++ TR_HW_CONTROLLED = 0, ++ TR_SW_TX = 1, ++}TR_SWITCH_STATE, *PTR_SWITCH_STATE; ++ ++ ++#define RTL_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30 ++ ++typedef struct buffer ++{ ++ struct buffer *next; ++ u32 *buf; ++ ++} buffer; ++ ++typedef struct rtl_reg_debug{ ++ unsigned int cmd; ++ struct { ++ unsigned char type; ++ unsigned char addr; ++ unsigned char page; ++ unsigned char length; ++ } head; ++ unsigned char buf[0xff]; ++}rtl_reg_debug; ++typedef struct _CHANNEL_LIST{ ++ u8 Channel[MAX_CHANNEL_NUMBER + 1]; ++ u8 Len; ++}CHANNEL_LIST, *PCHANNEL_LIST; ++ ++#define MAX_LD_SLOT_NUM 10 ++#define DEFAULT_SLOT_NUM 2 ++#define KEEP_ALIVE_INTERVAL 20 // in seconds. ++#define CHECK_FOR_HANG_PERIOD 2 //be equal to watchdog check time ++#define DEFAULT_KEEP_ALIVE_LEVEL 1 ++ ++typedef struct _link_detect_t ++{ ++ u32 RxFrameNum[MAX_LD_SLOT_NUM]; // number of Rx Frame / CheckForHang_period to determine link status ++ u16 SlotNum; // number of CheckForHang period to determine link status, default is 2 ++ u16 SlotIndex; ++ ++ u32 NumTxOkInPeriod; //number of packet transmitted during CheckForHang ++ u32 NumRxOkInPeriod; //number of packet received during CheckForHang ++ ++ u8 IdleCount; // (KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD) ++ u32 LastNumTxUnicast; ++ u32 LastNumRxUnicast; ++ ++ bool bBusyTraffic; //when it is set to 1, UI cann't scan at will. ++}link_detect_t, *plink_detect_t; ++ ++#if 0 ++ ++typedef struct tx_pendingbuf ++{ ++ struct ieee80211_txb *txb; ++ short ispending; ++ short descfrag; ++} tx_pendigbuf; ++ ++#endif ++ ++typedef struct Stats ++{ ++ unsigned long txrdu; ++// unsigned long rxrdu; ++ //unsigned long rxnolast; ++ //unsigned long rxnodata; ++// unsigned long rxreset; ++// unsigned long rxwrkaround; ++// unsigned long rxnopointer; ++ unsigned long rxok; ++ unsigned long rxurberr; ++ unsigned long rxstaterr; ++ unsigned long txnperr; ++ unsigned long txnpdrop; ++ unsigned long txresumed; ++// unsigned long rxerr; ++// unsigned long rxoverflow; ++// unsigned long rxint; ++ unsigned long txnpokint; ++// unsigned long txhpokint; ++// unsigned long txhperr; ++// unsigned long ints; ++// unsigned long shints; ++ unsigned long txoverflow; ++// unsigned long rxdmafail; ++// unsigned long txbeacon; ++// unsigned long txbeaconerr; ++ unsigned long txlpokint; ++ unsigned long txlpdrop; ++ unsigned long txlperr; ++ unsigned long txbeokint; ++ unsigned long txbedrop; ++ unsigned long txbeerr; ++ unsigned long txbkokint; ++ unsigned long txbkdrop; ++ unsigned long txbkerr; ++ unsigned long txviokint; ++ unsigned long txvidrop; ++ unsigned long txvierr; ++ unsigned long txvookint; ++ unsigned long txvodrop; ++ unsigned long txvoerr; ++ unsigned long txbeaconokint; ++ unsigned long txbeacondrop; ++ unsigned long txbeaconerr; ++ unsigned long txmanageokint; ++ unsigned long txmanagedrop; ++ unsigned long txmanageerr; ++ unsigned long txdatapkt; ++} Stats; ++ ++typedef struct ChnlAccessSetting { ++ u16 SIFS_Timer; ++ u16 DIFS_Timer; ++ u16 SlotTimeTimer; ++ u16 EIFS_Timer; ++ u16 CWminIndex; ++ u16 CWmaxIndex; ++}*PCHANNEL_ACCESS_SETTING,CHANNEL_ACCESS_SETTING; ++ ++ ++typedef enum _RT_RF_POWER_STATE ++{ ++ eRfOn, ++ eRfSleep, ++ eRfOff ++}RT_RF_POWER_STATE; ++typedef enum _RT_PS_MODE ++{ ++ eActive, // Active/Continuous access. ++ eMaxPs, // Max power save mode. ++ eFastPs // Fast power save mode. ++}RT_PS_MODE; ++// ++// Three wire mode. ++// ++#define IC_DEFAULT_THREE_WIRE 0 ++#define SW_THREE_WIRE 1 ++//RTL818xB ++#define SW_THREE_WIRE_BY_8051 2 ++#define HW_THREE_WIRE 3 ++#define HW_THREE_WIRE_BY_8051 4 ++//lzm add for write time out test ++typedef struct write_read_register ++{ ++ u32 address; ++ u32 content; ++ u32 flag; ++} write_read_register; ++//lzm add for write time out test ++typedef struct r8180_priv ++{ ++//lzm add for write time out test ++ struct write_read_register write_read_registers[200]; ++ u8 write_read_register_index; ++//lzm add for write time out test ++ ++ struct usb_device *udev; ++ short epromtype; ++ int irq; ++ struct ieee80211_device *ieee80211; ++ ++ short card_8187; /* O: rtl8180, 1:rtl8185 V B/C, 2:rtl8185 V D */ ++ short card_8187_Bversion; /* if TCR reports card V B/C this discriminates */ ++ short phy_ver; /* meaningful for rtl8225 1:A 2:B 3:C */ ++ short enable_gpio0; ++ enum card_type {PCI,MINIPCI,CARDBUS,USB/*rtl8187*/}card_type; ++ short hw_plcp_len; ++ short plcp_preamble_mode; ++ ++ spinlock_t irq_lock; ++// spinlock_t irq_th_lock; ++ spinlock_t tx_lock; ++//by amy for ps ++ spinlock_t rf_ps_lock; ++//by amy for ps ++ ++ u16 irq_mask; ++// short irq_enabled; ++ struct net_device *dev; ++ short chan; ++ short sens; ++ short max_sens; ++ u8 chtxpwr[15]; //channels from 1 to 14, 0 not used ++ u8 chtxpwr_ofdm[15]; //channels from 1 to 14, 0 not used ++ u8 cck_txpwr_base; ++ u8 ofdm_txpwr_base; ++ u8 challow[15]; //channels from 1 to 14, 0 not used ++ short up; ++ short crcmon; //if 1 allow bad crc frame reception in monitor mode ++// short prism_hdr; ++ ++// struct timer_list scan_timer; ++ /*short scanpending; ++ short stopscan;*/ ++// spinlock_t scan_lock; ++// u8 active_probe; ++ //u8 active_scan_num; ++ struct semaphore wx_sem; ++ struct semaphore set_chan_sem; ++// short hw_wep; ++ ++// short digphy; ++// short antb; ++// short diversity; ++// u8 cs_treshold; ++// short rcr_csense; ++ short rf_chip; ++// u32 key0[4]; ++ short (*rf_set_sens)(struct net_device *dev,short sens); ++ void (*rf_set_chan)(struct net_device *dev,short ch); ++ void (*rf_close)(struct net_device *dev); ++ void (*rf_init)(struct net_device *dev); ++ //short rate; ++ short promisc; ++ /*stats*/ ++ struct Stats stats; ++ struct _link_detect_t link_detect; //added on 1016.2008 ++ struct iw_statistics wstats; ++ struct proc_dir_entry *dir_dev; ++ ++ /*RX stuff*/ ++// u32 *rxring; ++// u32 *rxringtail; ++// dma_addr_t rxringdma; ++ struct urb **rx_urb; ++#ifdef THOMAS_BEACON ++ unsigned long *oldaddr; //lzm for 64bit CPU crash ++#endif ++ ++#ifdef THOMAS_TASKLET ++ atomic_t irt_counter;//count for irq_rx_tasklet ++#endif ++#ifdef JACKSON_NEW_RX ++ struct sk_buff **pp_rxskb; ++ int rx_inx; ++#endif ++ ++ short tx_urb_index; ++ ++ //struct buffer *rxbuffer; ++ //struct buffer *rxbufferhead; ++ //int rxringcount; ++ //u16 rxbuffersize; ++ ++ //struct sk_buff *rx_skb; ++ ++ //short rx_skb_complete; ++ ++ //u32 rx_prevlen; ++ //atomic_t tx_lp_pending; ++ //atomic_t tx_np_pending; ++ atomic_t tx_pending[0x10];//UART_PRIORITY+1 ++ ++#if 0 ++ /*TX stuff*/ ++ u32 *txlpring; ++ u32 *txhpring; ++ u32 *txnpring; ++ dma_addr_t txlpringdma; ++ dma_addr_t txhpringdma; ++ dma_addr_t txnpringdma; ++ u32 *txlpringtail; ++ u32 *txhpringtail; ++ u32 *txnpringtail; ++ u32 *txlpringhead; ++ u32 *txhpringhead; ++ u32 *txnpringhead; ++ struct buffer *txlpbufs; ++ struct buffer *txhpbufs; ++ struct buffer *txnpbufs; ++ struct buffer *txlpbufstail; ++ struct buffer *txhpbufstail; ++ struct buffer *txnpbufstail; ++ int txringcount; ++ int txbuffsize; ++ ++ //struct tx_pendingbuf txnp_pending; ++ struct tasklet_struct irq_tx_tasklet; ++#endif ++ struct tasklet_struct irq_rx_tasklet; ++ struct urb *rxurb_task; ++// u8 dma_poll_mask; ++ //short tx_suspend; ++ ++ /* adhoc/master mode stuff */ ++#if 0 ++ u32 *txbeacontail; ++ dma_addr_t txbeaconringdma; ++ u32 *txbeaconring; ++ int txbeaconcount; ++#endif ++// struct ieee_tx_beacon *beacon_buf; ++ //char *master_essid; ++// dma_addr_t beacondmabuf; ++ //u16 master_beaconinterval; ++// u32 master_beaconsize; ++ //u16 beacon_interval; ++ ++ //2 Tx Related variables ++ u16 ShortRetryLimit; ++ u16 LongRetryLimit; ++ u32 TransmitConfig; ++ u8 RegCWinMin; // For turbo mode CW adaptive. Added by Annie, 2005-10-27. ++ ++ //2 Rx Related variables ++ u16 EarlyRxThreshold; ++ u32 ReceiveConfig; ++ u8 AcmControl; ++ ++ u8 RFProgType; ++ ++ u8 retry_data; ++ u8 retry_rts; ++ u16 rts; ++ ++//by amy ++ long LastSignalStrengthInPercent; ++ long SignalStrength; ++ long SignalQuality; ++ u8 antenna_flag; ++ bool flag_beacon; ++//by amy ++//by amy for rate adaptive ++ struct timer_list rateadapter_timer; ++ u16 LastRetryCnt; ++ u16 LastRetryRate; ++ unsigned long LastTxokCnt; ++ unsigned long LastRxokCnt; ++ u16 CurrRetryCnt; ++ long RecvSignalPower; ++ unsigned long LastTxOKBytes; ++ u8 LastFailTxRate; ++ long LastFailTxRateSS; ++ u8 FailTxRateCount; ++ u32 LastTxThroughput; ++ unsigned long txokbytestotal; ++ //for up rate ++ unsigned short bTryuping; ++ u8 CurrTxRate; //the rate before up ++ u16 CurrRetryRate; ++ u16 TryupingCount; ++ u8 TryDownCountLowData; ++ u8 TryupingCountNoData; ++ ++ u8 CurrentOperaRate; ++// by lizhaoming used for Radio on/off ++#ifdef POLLING_METHOD_FOR_RADIO ++ struct timer_list gpio_polling_timer; ++ u8 polling_timer_on; ++ u8 wlan_first_up_flag1; ++#endif ++//by amy for rate adaptive ++//by amy for power save ++ struct timer_list watch_dog_timer; ++ bool bInactivePs; ++ bool bSwRfProcessing; ++ RT_RF_POWER_STATE eInactivePowerState; ++ RT_RF_POWER_STATE eRFPowerState; ++ u32 RfOffReason; ++ bool RFChangeInProgress; ++ bool bInHctTest; ++ bool SetRFPowerStateInProgress; ++ //u8 RFProgType; ++ bool bLeisurePs; ++ RT_PS_MODE dot11PowerSaveMode; ++ u32 NumRxOkInPeriod; ++ u32 NumTxOkInPeriod; ++ u8 RegThreeWireMode; ++ bool ps_mode; ++//by amy for power save ++//by amy for DIG ++ bool bDigMechanism; ++ bool bCCKThMechanism; ++ u8 InitialGain; ++ u8 StageCCKTh; ++ u8 RegBModeGainStage; ++ u8 RegDigOfdmFaUpTh; //added by david, 2008.3.6 ++ u8 DIG_NumberFallbackVote; ++ u8 DIG_NumberUpgradeVote; ++ u16 CCKUpperTh; ++ u16 CCKLowerTh; ++ u32 FalseAlarmRegValue; //added by david, 2008.3.6 ++//by amy for DIG ++//{ added by david for high power, 2008.3.11 ++ int UndecoratedSmoothedSS; ++ bool bRegHighPowerMechanism; ++ bool bToUpdateTxPwr; ++ u8 Z2HiPwrUpperTh; ++ u8 Z2HiPwrLowerTh; ++ u8 Z2RSSIHiPwrUpperTh; ++ u8 Z2RSSIHiPwrLowerTh; ++ // Current CCK RSSI value to determine CCK high power, asked by SD3 DZ, by Bruce, 2007-04-12. ++ u8 CurCCKRSSI; ++ bool bCurCCKPkt; ++ u32 wMacRegRfPinsOutput; ++ u32 wMacRegRfPinsSelect; ++ TR_SWITCH_STATE TrSwitchState; ++//} ++//{added by david for radio on/off ++ u8 radion; ++//} ++ struct ChnlAccessSetting ChannelAccessSetting; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) ++ struct work_struct reset_wq; ++#else ++ struct tq_struct reset_wq; ++#endif ++ ++#ifdef _RTL8187_EXT_PATCH_ ++ struct mshclass *mshobj; ++#endif ++ ++#ifdef LED ++ /* add for led controll */ ++ u8 EEPROMCustomerID; ++ RT_CID_TYPE CustomerID; ++ LED_8187 Gpio0Led; ++ LED_8187 SwLed0; ++ LED_8187 SwLed1; ++ u8 bEnableLedCtrl; ++ LED_STRATEGY_8187 LedStrategy; ++ u8 PsrValue; ++ struct work_struct Gpio0LedWorkItem; ++ struct work_struct SwLed0WorkItem; ++ struct work_struct SwLed1WorkItem; ++#endif ++ u8 driver_upping; ++#ifdef CPU_64BIT ++ u8 *usb_buf; ++ struct dma_pool *usb_pool; ++#endif ++ ++ ++#ifdef SW_ANTE_DIVERSITY ++ ++//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++// struct delayed_work SwAntennaWorkItem; ++//#else ++// struct work_struct SwAntennaWorkItem; ++//#endif ++ ++ bool bAntennaDiversityTimerIssued; ++ short antb; ++ short diversity; ++ bool AutoloadFailFlag; ++ u16 EEPROMVersion; ++ u8 EEPROMAntennaDiversity; ++ u16 EEPROMCSThreshold; ++ u8 EEPROMDefaultAntennaB; ++ u8 EEPROMDigitalPhy; ++ u32 EEPROMCSMethod; ++ u8 EEPROMGEPRFOffState; ++ // For HW antenna diversity, added by Roger, 2008.01.30. ++ u32 AdMainAntennaRxOkCnt; // Main antenna Rx OK count. ++ u32 AdAuxAntennaRxOkCnt; // Aux antenna Rx OK count. ++ bool bHWAdSwitched; // TRUE if we has switched default antenna by HW evaluation. ++ u8 EEPROMSwAntennaDiversity; ++ bool EEPROMDefaultAntenna1; ++ u8 RegSwAntennaDiversityMechanism;// 0:default from EEPROM, 1: disable, 2: enable. ++ bool bSwAntennaDiverity; ++ u8 RegDefaultAntenna;// 0: default from EEPROM, 1: main, 2: aux. Added by Roger, 2007.11.05. ++ bool bDefaultAntenna1; ++ //long SignalStrength; ++ long Stats_SignalStrength; ++ //long LastSignalStrengthInPercent; // In percentange, used for smoothing, e.g. Moving Average. ++ //long SignalQuality; // in 0-100 index. ++ long Stats_SignalQuality; ++ //long RecvSignalPower; // in dBm. ++ long Stats_RecvSignalPower; ++ u8 LastRxPktAntenna; // +by amy 080312 Antenn which received the lasted packet. 0: Aux, 1:Main. Added by Roger, 2008.01.25. ++ u32 AdRxOkCnt; ++ long AdRxSignalStrength; // Rx signal strength for Antenna Diversity, which had been smoothing, its valid range is [0,100]. ++ u8 CurrAntennaIndex; // Index to current Antenna (both Tx and Rx). ++ u8 AdTickCount; // Times of SwAntennaDiversityTimer happened. ++ u8 AdCheckPeriod; // # of period SwAntennaDiversityTimer to check Rx signal strength for SW Antenna Diversity. ++ u8 AdMinCheckPeriod; // Min value of AdCheckPeriod. ++ u8 AdMaxCheckPeriod; // Max value of AdCheckPeriod. ++ long AdRxSsThreshold; // Signal strength threshold to switch antenna. ++ long AdMaxRxSsThreshold; // Max value of AdRxSsThreshold. ++ bool bAdSwitchedChecking; // TRUE if we shall shall check Rx signal strength for last time switching antenna. ++ long AdRxSsBeforeSwitched; // Rx signal strength before we swithed antenna. ++ struct timer_list SwAntennaDiversityTimer; ++#endif ++ u8 commit; ++ ++//#ifdef ENABLE_DOT11D ++ u8 channel_plan; ++//#endif ++ u8 EEPROMSelectNewGPIO; ++}r8180_priv; ++ ++// for rtl8187 ++// now mirging to rtl8187B ++/* ++typedef enum{ ++ LOW_PRIORITY = 0x02, ++ NORM_PRIORITY ++ } priority_t; ++*/ ++//for rtl8187B ++typedef enum{ ++ BULK_PRIORITY = 0x01, ++ //RSVD0, ++ //RSVD1, ++ LOW_PRIORITY, ++ NORM_PRIORITY, ++ VO_PRIORITY, ++ VI_PRIORITY, //0x05 ++ BE_PRIORITY, ++ BK_PRIORITY, ++ RSVD2, ++ RSVD3, ++ BEACON_PRIORITY, //0x0A ++ HIGH_PRIORITY, ++ MANAGE_PRIORITY, ++ RSVD4, ++ RSVD5, ++ UART_PRIORITY //0x0F ++} priority_t; ++ ++typedef enum{ ++ NIC_8187 = 1, ++ NIC_8187B ++ } nic_t; ++ ++ ++typedef u32 AC_CODING; ++#define AC0_BE 0 // ACI: 0x00 // Best Effort ++#define AC1_BK 1 // ACI: 0x01 // Background ++#define AC2_VI 2 // ACI: 0x10 // Video ++#define AC3_VO 3 // ACI: 0x11 // Voice ++#define AC_MAX 4 // Max: define total number; Should not to be used as a real enum. ++ ++// ++// ECWmin/ECWmax field. ++// Ref: WMM spec 2.2.2: WME Parameter Element, p.13. ++// ++typedef union _ECW{ ++ u8 charData; ++ struct ++ { ++ u8 ECWmin:4; ++ u8 ECWmax:4; ++ }f; // Field ++}ECW, *PECW; ++ ++// ++// ACI/AIFSN Field. ++// Ref: WMM spec 2.2.2: WME Parameter Element, p.12. ++// ++typedef union _ACI_AIFSN{ ++ u8 charData; ++ ++ struct ++ { ++ u8 AIFSN:4; ++ u8 ACM:1; ++ u8 ACI:2; ++ u8 Reserved:1; ++ }f; // Field ++}ACI_AIFSN, *PACI_AIFSN; ++ ++// ++// AC Parameters Record Format. ++// Ref: WMM spec 2.2.2: WME Parameter Element, p.12. ++// ++typedef union _AC_PARAM{ ++ u32 longData; ++ u8 charData[4]; ++ ++ struct ++ { ++ ACI_AIFSN AciAifsn; ++ ECW Ecw; ++ u16 TXOPLimit; ++ }f; // Field ++}AC_PARAM, *PAC_PARAM; ++ ++#ifdef JOHN_HWSEC ++struct ssid_thread { ++ struct net_device *dev; ++ u8 name[IW_ESSID_MAX_SIZE + 1]; ++}; ++#endif ++ ++short rtl8180_tx(struct net_device *dev,u32* skbuf, int len,priority_t priority,short morefrag,short rate); ++ ++#ifdef JOHN_TKIP ++u32 read_cam(struct net_device *dev, u8 addr); ++void write_cam(struct net_device *dev, u8 addr, u32 data); ++#endif ++u8 read_nic_byte(struct net_device *dev, int x); ++u8 read_nic_byte_E(struct net_device *dev, int x); ++u32 read_nic_dword(struct net_device *dev, int x); ++u16 read_nic_word(struct net_device *dev, int x) ; ++void write_nic_byte(struct net_device *dev, int x,u8 y); ++void write_nic_byte_E(struct net_device *dev, int x,u8 y); ++void write_nic_word(struct net_device *dev, int x,u16 y); ++void write_nic_dword(struct net_device *dev, int x,u32 y); ++void force_pci_posting(struct net_device *dev); ++ ++void rtl8180_rtx_disable(struct net_device *); ++void rtl8180_rx_enable(struct net_device *); ++void rtl8180_tx_enable(struct net_device *); ++ ++void rtl8180_disassociate(struct net_device *dev); ++//void fix_rx_fifo(struct net_device *dev); ++void rtl8185_set_rf_pins_enable(struct net_device *dev,u32 a); ++ ++void rtl8180_set_anaparam(struct net_device *dev,u32 a); ++void rtl8185_set_anaparam2(struct net_device *dev,u32 a); ++void rtl8180_update_msr(struct net_device *dev); ++int rtl8180_down(struct net_device *dev); ++int rtl8180_up(struct net_device *dev); ++void rtl8180_commit(struct net_device *dev); ++void rtl8180_set_chan(struct net_device *dev,short ch); ++void write_phy(struct net_device *dev, u8 adr, u8 data); ++void write_phy_cck(struct net_device *dev, u8 adr, u32 data); ++void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data); ++void rtl8185_tx_antenna(struct net_device *dev, u8 ant); ++void rtl8187_set_rxconf(struct net_device *dev); ++bool MgntActSet_RF_State(struct net_device *dev,RT_RF_POWER_STATE StateToSet,u32 ChangeSource); ++void IPSEnter(struct net_device *dev); ++void IPSLeave(struct net_device *dev); ++#ifdef POLLING_METHOD_FOR_RADIO ++void gpio_change_polling(unsigned long data); ++#endif ++bool SetRFPowerState(struct net_device *dev,RT_RF_POWER_STATE eRFPowerState); ++void rtl8180_patch_ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee); ++#ifdef _RTL8187_EXT_PATCH_ ++extern int r8180_wx_set_channel(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); ++#endif ++#ifdef JOHN_TKIP ++void EnableHWSecurityConfig8187(struct net_device *dev); ++void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, u8 *MacAddr, u8 DefaultKey, u32 *KeyContent ); ++ ++#endif ++ ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8187_led.c linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8187_led.c +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8187_led.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8187_led.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,1629 @@ ++/*++ ++Copyright (c) Realtek Semiconductor Corp. All rights reserved. ++ ++Module Name: ++ r8187_led.c ++ ++Abstract: ++ RTL8187 LED control functions ++ ++Major Change History: ++ When Who What ++ ---------- --------------- ------------------------------- ++ 2006-09-07 Xiong Created ++ ++Notes: ++ ++--*/ ++ ++/*--------------------------Include File------------------------------------*/ ++#include "ieee80211/ieee80211.h" ++#include "r8180_hw.h" ++#include "r8187.h" ++#include "r8180_93cx6.h" ++#include "r8187_led.h" ++ ++/** ++* ++* Initialization function for Sw Leds controll. ++* ++* \param dev The net device for this driver. ++* \return void. ++* ++* Note: ++* ++*/ ++ ++void ++InitSwLeds( ++ struct net_device *dev ++ ) ++{ ++ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u16 usValue; ++// printk("========>%s()\n", __FUNCTION__); ++ ++// priv->CustomerID = RT_CID_87B_DELL; //by lizhaoming for DELL 2008.6.3 ++ priv->CustomerID = RT_CID_DEFAULT; //just set to default now ++ priv->bEnableLedCtrl = 1; ++ priv->PsrValue = read_nic_byte(dev, PSR); ++ usValue = eprom_read(dev, EEPROM_SW_REVD_OFFSET >> 1); ++ priv->EEPROMCustomerID = (u8)( usValue & EEPROM_CID_MASK ); ++ DMESG("EEPROM Customer ID: %02X", priv->EEPROMCustomerID); ++ ++ if(priv->CustomerID == RT_CID_DEFAULT) ++ { // If we have not yet change priv->CustomerID in register, ++ // we initialzie it from that of EEPROM with proper translation, 2006.07.03, by rcnjko. ++ switch(priv->EEPROMCustomerID) ++ { ++ case EEPROM_CID_RSVD0: ++ case EEPROM_CID_RSVD1: ++ priv->CustomerID = RT_CID_DEFAULT; ++ break; ++ ++ case EEPROM_CID_ALPHA0: ++ priv->CustomerID = RT_CID_8187_ALPHA0; ++ break; ++ ++ case EEPROM_CID_SERCOMM_PS: ++ priv->CustomerID = RT_CID_8187_SERCOMM_PS; ++ break; ++ ++ case EEPROM_CID_HW_LED: ++ priv->CustomerID = RT_CID_8187_HW_LED; ++ break; ++ ++ case EEPROM_CID_QMI: ++ priv->CustomerID = RT_CID_87B_QMI; ++ break; ++ ++ case EEPROM_CID_DELL: ++ priv->CustomerID = RT_CID_87B_DELL; ++ break; ++ ++ default: ++ // Invalid value, so, we use default value instead. ++ priv->CustomerID = RT_CID_DEFAULT; ++ break; ++ } ++ } ++ switch(priv->CustomerID) ++ { ++ case RT_CID_DEFAULT: ++ priv->LedStrategy = SW_LED_MODE0; ++ break; ++ ++ case RT_CID_8187_ALPHA0: ++ priv->LedStrategy = SW_LED_MODE1; ++ break; ++ ++ case RT_CID_8187_SERCOMM_PS: ++ priv->LedStrategy = SW_LED_MODE3; ++ break; ++ ++ case RT_CID_87B_QMI: ++ priv->LedStrategy = SW_LED_MODE4; ++ break; ++ ++ case RT_CID_87B_DELL: ++ priv->LedStrategy = SW_LED_MODE5; ++ break; ++ ++ case RT_CID_8187_HW_LED: ++ priv->LedStrategy = HW_LED; ++ break; ++ ++ default: ++ priv->LedStrategy = SW_LED_MODE0; ++ break; ++ } ++ ++ InitLed8187(dev, ++ &(priv->Gpio0Led), ++ LED_PIN_GPIO0, ++ Gpio0LedBlinkTimerCallback); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ INIT_WORK(&priv->Gpio0LedWorkItem, ++ (void(*)(void*))Gpio0LedWorkItemCallback, dev); ++ ++ InitLed8187(dev, ++ &(priv->SwLed0), ++ LED_PIN_LED0, ++ SwLed0BlinkTimerCallback); ++ INIT_WORK(&priv->SwLed0WorkItem, ++ (void(*)(void*))SwLed0WorkItemCallback, dev); ++ ++ InitLed8187(dev, ++ &(priv->SwLed1), ++ LED_PIN_LED1, ++ SwLed1BlinkTimerCallback); ++ INIT_WORK(&priv->SwLed1WorkItem, ++ (void(*)(void*))SwLed1WorkItemCallback, dev); ++#else ++INIT_WORK(&priv->Gpio0LedWorkItem, ++ Gpio0LedWorkItemCallback); ++ ++ InitLed8187(dev, ++ &(priv->SwLed0), ++ LED_PIN_LED0, ++ SwLed0BlinkTimerCallback); ++ INIT_WORK(&priv->SwLed0WorkItem, ++ SwLed0WorkItemCallback); ++ ++ InitLed8187(dev, ++ &(priv->SwLed1), ++ LED_PIN_LED1, ++ SwLed1BlinkTimerCallback); ++ INIT_WORK(&priv->SwLed1WorkItem, ++ SwLed1WorkItemCallback); ++#endif ++} ++ ++void ++DeInitSwLeds( ++ struct net_device *dev ++ ) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++// printk("=========>%s In\n", __FUNCTION__); ++ DeInitLed8187(dev, &(priv->Gpio0Led)); ++ DeInitLed8187(dev, &(priv->SwLed0)); ++ DeInitLed8187(dev, &(priv->SwLed1)); ++} ++ ++void ++InitLed8187( ++ struct net_device *dev, ++ PLED_8187 pLed, ++ LED_PIN_8187 LedPin, ++ void * BlinkCallBackFunc) ++{ ++// printk("=========>%s In\n", __FUNCTION__); ++ pLed->LedPin = LedPin; ++ ++ pLed->bLedOn = 0; ++ pLed->CurrLedState = LED_OFF; ++ ++ pLed->bLedBlinkInProgress = 0; ++ pLed->BlinkTimes = 0; ++ pLed->BlinkingLedState = LED_OFF; ++ ++ init_timer(&(pLed->BlinkTimer)); ++ pLed->BlinkTimer.data = (unsigned long)dev; ++ pLed->BlinkTimer.function = BlinkCallBackFunc; ++ //PlatformInitializeTimer(dev, &(pLed->BlinkTimer), BlinkCallBackFunc); ++} ++ ++void ++DeInitLed8187( ++ struct net_device *dev, ++ PLED_8187 pLed) ++{ ++ //printk("=========>%s In\n", __FUNCTION__); ++ //PlatformCancelTimer(dev, &(pLed->BlinkTimer)); ++ del_timer_sync(&(pLed->BlinkTimer)); ++ // We should reset bLedBlinkInProgress if we cancel the LedControlTimer, 2005.03.10, by rcnjko. ++ pLed->bLedBlinkInProgress = 0; ++} ++ ++void ++LedControl8187( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++// printk("=========>%s In\n", __FUNCTION__); ++ if( priv->bEnableLedCtrl == 0) ++ return; ++ ++ ++ if( priv->eRFPowerState != eRfOn && ++ (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX || ++ LedAction == LED_CTL_SITE_SURVEY || ++ LedAction == LED_CTL_LINK || ++ LedAction == LED_CTL_NO_LINK) ) ++ { ++ return; ++ } ++ ++ ++ switch(priv->LedStrategy) ++ { ++ case SW_LED_MODE0: ++ SwLedControlMode0(dev, LedAction); ++ break; ++ ++ case SW_LED_MODE1: ++ SwLedControlMode1(dev, LedAction); ++ break; ++ ++ case SW_LED_MODE2: ++ SwLedControlMode2(dev, LedAction); ++ break; ++ ++ case SW_LED_MODE3: ++ SwLedControlMode3(dev, LedAction); ++ break; ++ case SW_LED_MODE4: ++ SwLedControlMode4(dev, LedAction); ++ break; ++ ++ case SW_LED_MODE5: ++ SwLedControlMode5(dev, LedAction); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++ ++// ++// Description: ++// Implement each led action for SW_LED_MODE0. ++// This is default strategy. ++// ++void ++SwLedControlMode0( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ PLED_8187 pLed = &(priv->Gpio0Led); ++ ++// printk("===+++++++++++++++======>%s In\n", __FUNCTION__); ++ // Decide led state ++ switch(LedAction) ++ { ++ case LED_CTL_TX: ++ case LED_CTL_RX: ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ pLed->CurrLedState = LED_BLINK_NORMAL; ++ pLed->BlinkTimes = 2; ++ // printk("===========>LED_CTL_TX/RX \n"); ++ } ++ else ++ { ++ return; ++ } ++ break; ++ ++ case LED_CTL_SITE_SURVEY: ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ pLed->CurrLedState = LED_BLINK_SLOWLY; ++ // pLed->BlinkTimes = 10; ++ //printk("===========>LED_CTL_SURVEY \n"); ++ } ++ else ++ { ++ return; ++ } ++ break; ++ ++ case LED_CTL_LINK: ++ // printk("===========>associate commplite LED_CTL_LINK\n"); ++ pLed->CurrLedState = LED_ON; ++ break; ++ ++ case LED_CTL_NO_LINK: ++ pLed->CurrLedState = LED_OFF; ++ break; ++ ++ case LED_CTL_POWER_ON: ++ // printk("===========>LED_CTL_POWER_ON\n"); ++ pLed->CurrLedState = LED_POWER_ON_BLINK; ++ break; ++ ++ case LED_CTL_POWER_OFF: ++ pLed->CurrLedState = LED_OFF; ++ break; ++ ++ default: ++ return; ++ break; ++ } ++ ++ // Change led state. ++ switch(pLed->CurrLedState) ++ { ++ case LED_ON: ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ SwLedOn(dev, pLed); ++ } ++ break; ++ ++ case LED_OFF://modified by lizhaoming 2008.6.23 ++ // if( pLed->bLedBlinkInProgress == 0 ) ++ // { ++ // SwLedOff(dev, pLed); ++ // } ++ ++ if(pLed->bLedBlinkInProgress )/////////lizhaoming ++ { ++ del_timer_sync(&(pLed->BlinkTimer)); ++ pLed->bLedBlinkInProgress = FALSE; ++ } ++ SwLedOff(dev, pLed); ++ break; ++ ++ case LED_BLINK_NORMAL: ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ pLed->bLedBlinkInProgress = 1; ++ if( pLed->bLedOn ) ++ pLed->BlinkingLedState = LED_OFF; ++ else ++ pLed->BlinkingLedState = LED_ON; ++ ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_NORMAL_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); ++ } ++ break; ++ ++ case LED_BLINK_SLOWLY: ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ //printk("=======>%s SLOWLY\n", __func__); ++ pLed->bLedBlinkInProgress = 1; ++ // if( pLed->bLedOn ) ++ pLed->BlinkingLedState = LED_OFF;//for LED_SHIN is LED on ++ // else ++ // pLed->BlinkingLedState = LED_ON; ++ ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL)); ++ } ++ break; ++ ++ case LED_POWER_ON_BLINK: ++ SwLedOn(dev, pLed); ++#ifdef LED_SHIN ++ mdelay(100); ++ SwLedOff(dev, pLed); ++#endif ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++// ++// Description: ++// Implement each led action for SW_LED_MODE1. ++// For example, this is applied by ALPHA. ++// ++void ++SwLedControlMode1( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ PLED_8187 pLed0 = &(priv->SwLed0); ++ PLED_8187 pLed1 = &(priv->SwLed1); ++// printk("=====++++++++++++++++++++++====>%s In\n", __FUNCTION__); ++ ++ switch(LedAction) ++ { ++ case LED_CTL_TX: ++ if( pLed0->bLedBlinkInProgress == 0 ) ++ { ++ pLed0->CurrLedState = LED_BLINK_NORMAL; ++ pLed0->BlinkTimes = 2; ++ pLed0->bLedBlinkInProgress = 1; ++ if( pLed0->bLedOn ) ++ pLed0->BlinkingLedState = LED_OFF; ++ else ++ pLed0->BlinkingLedState = LED_ON; ++ ++ //pLed0->BlinkTimer.expires = jiffies + LED_BLINK_NORMAL_INTERVAL; ++ //add_timer(&(pLed0->BlinkTimer)); ++ mod_timer(&pLed0->BlinkTimer, jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed0->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); ++ } ++ break; ++ ++ case LED_CTL_LINK: ++ pLed0->CurrLedState = LED_ON; ++ if( pLed0->bLedBlinkInProgress == 0 ) ++ { ++ SwLedOn(dev, pLed0); ++ } ++ break; ++ ++ case LED_CTL_NO_LINK: ++ pLed0->CurrLedState = LED_OFF; ++ if( pLed0->bLedBlinkInProgress == 0 ) ++ { ++ SwLedOff(dev, pLed0); ++ } ++ break; ++ ++ case LED_CTL_POWER_ON: ++ pLed0->CurrLedState = LED_OFF; ++ SwLedOff(dev, pLed0); ++ ++ pLed1->CurrLedState = LED_ON; ++ SwLedOn(dev, pLed1); ++ ++ break; ++ ++ case LED_CTL_POWER_OFF: ++ pLed0->CurrLedState = LED_OFF; ++ SwLedOff(dev, pLed0); ++ ++ pLed1->CurrLedState = LED_OFF; ++ SwLedOff(dev, pLed1); ++ break; ++ ++ case LED_CTL_SITE_SURVEY: ++ if( pLed0->bLedBlinkInProgress == 0 ) ++ { ++ pLed0->CurrLedState = LED_BLINK_SLOWLY;; ++ pLed0->BlinkTimes = 10; ++ pLed0->bLedBlinkInProgress = 1; ++ if( pLed0->bLedOn ) ++ pLed0->BlinkingLedState = LED_OFF; ++ else ++ pLed0->BlinkingLedState = LED_ON; ++ ++ //pLed0->BlinkTimer.expires = jiffies + LED_BLINK_SLOWLY_INTERVAL; ++ //add_timer(&(pLed0->BlinkTimer)); ++ mod_timer(&pLed0->BlinkTimer, jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed0->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); ++ } ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++// ++// Description: ++// Implement each led action for SW_LED_MODE2, ++// which is customized for AzWave 8187 minicard. ++// 2006.04.03, by rcnjko. ++// ++void ++SwLedControlMode2( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ PLED_8187 pLed = &(priv->Gpio0Led); ++ ++// printk("====+++++++++++++++++++++=====>%s In\n", __FUNCTION__); ++ // Decide led state ++ switch(LedAction) ++ { ++ case LED_CTL_TX: ++ case LED_CTL_RX: ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ pLed->bLedBlinkInProgress = 1; ++ ++ pLed->CurrLedState = LED_BLINK_NORMAL; ++ pLed->BlinkTimes = 2; ++ ++ if( pLed->bLedOn ) ++ pLed->BlinkingLedState = LED_OFF; ++ else ++ pLed->BlinkingLedState = LED_ON; ++ ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_NORMAL_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); ++ } ++ break; ++ ++ case LED_CTL_SITE_SURVEY: ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ pLed->bLedBlinkInProgress = 1; ++ ++ //if( dev->MgntInfo.mAssoc || ++ // dev->MgntInfo.mIbss ) ++ //{ ++ pLed->CurrLedState = LED_SCAN_BLINK; ++ pLed->BlinkTimes = 4; ++ //} ++ //else ++ //{ ++ // pLed->CurrLedState = LED_NO_LINK_BLINK; ++ // pLed->BlinkTimes = 24; ++ //} ++ ++ if( pLed->bLedOn ) ++ { ++ pLed->BlinkingLedState = LED_OFF; ++ //pLed->BlinkTimer.expires = jiffies + LED_CM2_BLINK_ON_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_CM2_BLINK_ON_INTERVAL); ++ } ++ else ++ { ++ pLed->BlinkingLedState = LED_ON; ++ //pLed->BlinkTimer.expires = jiffies + LED_CM2_BLINK_OFF_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM2_BLINK_OFF_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_CM2_BLINK_OFF_INTERVAL); ++ } ++ } ++ else ++ { ++ if(pLed->CurrLedState != LED_NO_LINK_BLINK) ++ { ++ pLed->CurrLedState = LED_SCAN_BLINK; ++ /* ++ if( dev->MgntInfo.mAssoc || ++ dev->MgntInfo.mIbss ) ++ { ++ pLed->CurrLedState = LED_SCAN_BLINK; ++ } ++ else ++ { ++ pLed->CurrLedState = LED_NO_LINK_BLINK; ++ } ++ */ ++ } ++ } ++ break; ++ ++ case LED_CTL_NO_LINK: ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ pLed->bLedBlinkInProgress = 1; ++ ++ pLed->CurrLedState = LED_NO_LINK_BLINK; ++ pLed->BlinkTimes = 24; ++ ++ if( pLed->bLedOn ) ++ { ++ pLed->BlinkingLedState = LED_OFF; ++ //pLed->BlinkTimer.expires = jiffies + LED_CM2_BLINK_ON_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_CM2_BLINK_ON_INTERVAL); ++ } ++ else ++ { ++ pLed->BlinkingLedState = LED_ON; ++ //pLed->BlinkTimer.expires = jiffies + LED_CM2_BLINK_OFF_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM2_BLINK_OFF_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_CM2_BLINK_OFF_INTERVAL); ++ } ++ } ++ else ++ { ++ pLed->CurrLedState = LED_NO_LINK_BLINK; ++ } ++ break; ++ ++ case LED_CTL_LINK: ++ pLed->CurrLedState = LED_ON; ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ SwLedOn(dev, pLed); ++ } ++ break; ++ ++ case LED_CTL_POWER_OFF: ++ pLed->CurrLedState = LED_OFF; ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ SwLedOff(dev, pLed); ++ } ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++ ++// ++// Description: ++// Implement each led action for SW_LED_MODE3, ++// which is customized for Sercomm Printer Server case. ++// 2006.04.21, by rcnjko. ++// ++void ++SwLedControlMode3( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ PLED_8187 pLed = &(priv->Gpio0Led); ++ ++// printk("=====+++++++++++++++++++====>%s In\n", __FUNCTION__); ++ // Decide led state ++ switch(LedAction) ++ { ++ case LED_CTL_TX: ++ case LED_CTL_RX: ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ pLed->bLedBlinkInProgress = 1; ++ ++ pLed->CurrLedState = LED_BLINK_CM3; ++ pLed->BlinkTimes = 2; ++ ++ if( pLed->bLedOn ) ++ pLed->BlinkingLedState = LED_OFF; ++ else ++ pLed->BlinkingLedState = LED_ON; ++ ++ //pLed->BlinkTimer.expires = jiffies + LED_CM3_BLINK_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM3_BLINK_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_CM3_BLINK_INTERVAL); ++ } ++ break; ++ ++ case LED_CTL_SITE_SURVEY: ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ pLed->bLedBlinkInProgress = 1; ++ ++ pLed->CurrLedState = LED_BLINK_CM3; ++ pLed->BlinkTimes = 10; ++ ++ if( pLed->bLedOn ) ++ pLed->BlinkingLedState = LED_OFF; ++ else ++ pLed->BlinkingLedState = LED_ON; ++ ++ //pLed->BlinkTimer.expires = jiffies + LED_CM3_BLINK_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM3_BLINK_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_CM3_BLINK_INTERVAL); ++ } ++ break; ++ ++ case LED_CTL_LINK: ++ pLed->CurrLedState = LED_ON; ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ SwLedOn(dev, pLed); ++ } ++ break; ++ ++ case LED_CTL_NO_LINK: ++ pLed->CurrLedState = LED_OFF; ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ SwLedOff(dev, pLed); ++ } ++ break; ++ ++ case LED_CTL_POWER_ON: ++ pLed->CurrLedState = LED_POWER_ON_BLINK; ++ SwLedOn(dev, pLed); ++ mdelay(100); ++ SwLedOff(dev, pLed); ++ break; ++ ++ case LED_CTL_POWER_OFF: ++ pLed->CurrLedState = LED_OFF; ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ SwLedOff(dev, pLed); ++ } ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++// added by lizhaoming 2008.6.2 ++// ++// Description: ++// Implement each led action for SW_LED_MODE4, ++// which is customized for QMI 8187B minicard. ++// 2008.04.21, by chiyokolin. ++// ++void ++SwLedControlMode4( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++ ) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ PLED_8187 pLed = &(priv->Gpio0Led); ++ ++ //printk("=====+++++++++++++++++++++====>%s In\n", __FUNCTION__); ++ // Decide led state ++ switch(LedAction) ++ { ++ case LED_CTL_TX: ++ case LED_CTL_RX: ++ //if( pLed->bLedBlinkInProgress == false && !priv->bScanInProgress)//????? ++ if( pLed->bLedBlinkInProgress == 0) ++ { ++ pLed->bLedBlinkInProgress = 1; ++ ++ pLed->CurrLedState = LED_BLINK_NORMAL; ++ pLed->BlinkTimes = 2; ++ ++ if( pLed->bLedOn ) ++ pLed->BlinkingLedState = LED_OFF; ++ else ++ pLed->BlinkingLedState = LED_ON; ++ ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_NORMAL_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); ++ //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); ++ } ++ else ++ //printk("----->LED_CTL_RX/TX bLedBlinkInProgress\n"); ++ ++ break; ++ ++ case LED_CTL_SITE_SURVEY: ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ ++ pLed->bLedBlinkInProgress = 1; ++ //if( priv->MgntInfo.mAssoc || priv->MgntInfo.mIbss )//////////?????? ++ //{ ++ pLed->CurrLedState = LED_SCAN_BLINK; ++ pLed->BlinkTimes = 10; ++ ++ pLed->BlinkingLedState = LED_ON; ++ ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_NORMAL_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); ++ //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); ++ //} ++ //else ++ //{ ++ // pLed->CurrLedState = LED_NO_LINK_BLINK; ++ // pLed->BlinkTimes = 24; ++ // ++ // if( pLed->bLedOn ) ++ // { ++ // pLed->BlinkingLedState = LED_OFF; ++ // ++ // pLed->BlinkTimer.expires = jiffies + LED_CM4_BLINK_ON_INTERVAL; ++ // add_timer(&(pLed->BlinkTimer)); ++ // //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_CM4_BLINK_ON_INTERVAL); ++ // } ++ // else ++ // { ++ // pLed->BlinkingLedState = LED_ON; ++ ++ // pLed->BlinkTimer.expires = jiffies + LED_CM4_BLINK_OFF_INTERVAL; ++ // add_timer(&(pLed->BlinkTimer)); ++ // //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_CM4_BLINK_OFF_INTERVAL); ++ // } ++ //} ++ } ++ else ++ { ++ if(pLed->CurrLedState != LED_NO_LINK_BLINK) ++ { ++ //if( priv->MgntInfo.mAssoc || priv->MgntInfo.mIbss )//??????????? ++ //{ ++ //} ++ //else ++ //{ ++ // pLed->CurrLedState = LED_NO_LINK_BLINK; ++ //} ++ } ++ ++ //printk("----->LED_CTL_SITE_SURVEY bLedBlinkInProgress\n"); ++ } ++ break; ++ ++ case LED_CTL_NO_LINK: ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ pLed->bLedBlinkInProgress = 1; ++ ++ pLed->CurrLedState = LED_NO_LINK_BLINK; ++ pLed->BlinkTimes = 24; ++ ++ if( pLed->bLedOn ) ++ { ++ pLed->BlinkingLedState = LED_OFF; ++ ++ //pLed->BlinkTimer.expires = jiffies + LED_CM4_BLINK_ON_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM4_BLINK_ON_INTERVAL)); ++ //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_CM4_BLINK_ON_INTERVAL); ++ } ++ else ++ { ++ pLed->BlinkingLedState = LED_ON; ++ ++ //pLed->BlinkTimer.expires = jiffies + LED_CM4_BLINK_OFF_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM4_BLINK_OFF_INTERVAL)); ++ //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_CM4_BLINK_OFF_INTERVAL); ++ } ++ } ++ else ++ { ++ pLed->CurrLedState = LED_NO_LINK_BLINK; ++ //printk("----->LED_CTL_NO_LINK bLedBlinkInProgress\n"); ++ } ++ break; ++ ++ case LED_CTL_LINK: ++ pLed->CurrLedState = LED_ON; ++ if( pLed->bLedBlinkInProgress == 0) ++ { ++ SwLedOn(dev, pLed); ++ } ++ else ++ ;//printk("----->LED_CTL_LINK bLedBlinkInProgress\n"); ++ ++ break; ++ ++ case LED_CTL_POWER_OFF: ++ pLed->CurrLedState = LED_OFF; ++ if(pLed->bLedBlinkInProgress) ++ { ++ printk("----->LED_CTL_POWER_OFF bLedBlinkInProgress\n"); ++ ++ //PlatformCancelTimer(Adapter, &(pLed->BlinkTimer)); ++ del_timer_sync(&(pLed->BlinkTimer)); ++ pLed->bLedBlinkInProgress = 0; ++ } ++ SwLedOff(dev, pLed); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++ ++ ++//added by lizhaoming 2008.6.3 ++// ++// Description: ++// Implement each led action for SW_LED_MODE5, ++// which is customized for DELL 8187B minicard. ++// 2008.04.24, by chiyokolin. ++// ++void ++SwLedControlMode5( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++ ) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ PLED_8187 pLed = &(priv->Gpio0Led); ++ ++ // Decide led state ++ //printk("====++++++++++++++++++++++=====>%s In\n", __FUNCTION__); ++ switch(LedAction) ++ { ++ case LED_CTL_TX: ++ case LED_CTL_RX: ++ case LED_CTL_SITE_SURVEY: ++ case LED_CTL_POWER_ON: ++ case LED_CTL_NO_LINK: ++ case LED_CTL_LINK: ++ pLed->CurrLedState = LED_ON; ++ if( pLed->bLedBlinkInProgress == 0 ) ++ { ++ pLed->bLedBlinkInProgress = 1; ++ if(! pLed->bLedOn ) ++ pLed->BlinkingLedState = LED_ON; ++ else ++ break; ++ ++ //printk("====++++++++++++++++++++++=====>%s In LED:%d\n", __FUNCTION__, pLed->bLedOn); ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_NORMAL_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); ++ // SwLedOn(dev, pLed); ++ } ++ else ++ ;//printk("----->LED_CTL_LINK bLedBlinkInProgress\n"); ++ ++ break; ++ ++ case LED_CTL_POWER_OFF: ++ pLed->CurrLedState = LED_OFF; ++ // printk("<====++++++++++++++++++++++=====%s In LED:%d\n", __FUNCTION__, pLed->bLedOn); ++ if(pLed->bLedBlinkInProgress) ++ { ++ // printk("----->LED_CTL_POWER_OFF bLedBlinkInProgress\n"); ++ ++ //PlatformCancelTimer(Adapter, &(pLed->BlinkTimer)); ++ del_timer_sync(&(pLed->BlinkTimer)); ++ pLed->bLedBlinkInProgress = 0; ++ } ++ SwLedOff(dev, pLed); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++// ++// Callback fuction of the timer, Gpio0Led.BlinkTimer. ++// ++void ++Gpio0LedBlinkTimerCallback( ++ unsigned long data ++ ) ++{ ++ struct net_device *dev = (struct net_device *)data; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++// printk("=========>%s In\n", __FUNCTION__); ++ PlatformSwLedBlink(dev, &(priv->Gpio0Led)); ++} ++ ++ ++ ++// ++// Callback fuction of the timer, SwLed0.BlinkTimer. ++// ++void ++SwLed0BlinkTimerCallback( ++ unsigned long data ++ ) ++{ ++ struct net_device *dev = (struct net_device *)data; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++// printk("=========>%s In\n", __FUNCTION__); ++ PlatformSwLedBlink(dev, &(priv->SwLed0)); ++} ++ ++ ++ ++// ++// Callback fuction of the timer, SwLed1.BlinkTimer. ++// ++void ++SwLed1BlinkTimerCallback( ++ unsigned long data ++ ) ++{ ++ struct net_device *dev = (struct net_device *)data; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++// printk("=========>%s In\n", __FUNCTION__); ++ PlatformSwLedBlink(dev, &(priv->SwLed1)); ++} ++ ++void ++PlatformSwLedBlink( ++ struct net_device *dev, ++ PLED_8187 pLed ++ ) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++// printk("=========>%s In\n", __FUNCTION__); ++ switch(pLed->LedPin) ++ { ++ case LED_PIN_GPIO0: ++ schedule_work(&(priv->Gpio0LedWorkItem)); ++ break; ++ ++ case LED_PIN_LED0: ++ schedule_work(&(priv->SwLed0WorkItem)); ++ break; ++ ++ case LED_PIN_LED1: ++ schedule_work(&(priv->SwLed1WorkItem)); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++// ++// Callback fucntion of the workitem for SW LEDs. ++// 2006.03.01, by rcnjko. ++// ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++void Gpio0LedWorkItemCallback(struct work_struct *work) ++{ ++ struct r8180_priv *priv = container_of(work, struct r8180_priv,Gpio0LedWorkItem); ++ struct net_device *dev = priv->ieee80211->dev; ++#else ++void ++Gpio0LedWorkItemCallback( ++ void * Context ++ ) ++{ ++ struct net_device *dev = (struct net_device *)Context; ++ struct r8180_priv *priv = ieee80211_priv(dev); ++#endif ++ PLED_8187 pLed = &(priv->Gpio0Led); ++ if (priv == NULL || dev == NULL){ ++// printk("=========>%s In\n", __FUNCTION__); ++ //printk("ft=====================>%s()\n", __FUNCTION__); ++ } ++ ++#if 0 // by lizahoming 2008.6.3 ++ if(priv->LedStrategy == SW_LED_MODE2) ++ SwLedCm2Blink(dev, pLed); ++ else ++ SwLedBlink(dev, pLed); ++#endif ++ ++#if 1 // by lizahoming 2008.6.3 ++ switch(priv->LedStrategy) ++ { ++ case SW_LED_MODE2: ++ SwLedCm2Blink(dev, pLed); ++ break; ++ case SW_LED_MODE4: ++ SwLedCm4Blink(dev, pLed); ++ break; ++ default: ++ SwLedBlink(dev, pLed); ++ break; ++ } ++#endif ++ ++ //LeaveCallbackOfRtWorkItem( &(usbdevice->Gpio0LedWorkItem) ); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++void SwLed0WorkItemCallback(struct work_struct *work) ++{ ++ //struct r8180_priv *priv = container_of(work, struct r8180_priv, SwLed0WorkItem); ++ //struct net_device *dev = priv->dev; ++#else ++void SwLed0WorkItemCallback(void * Context) ++{ ++ //struct net_device *dev = (struct net_device *)Context; ++ //struct r8180_priv *priv = ieee80211_priv(dev); ++#endif ++ //SwLedBlink(dev, &(priv->SwLed0)); ++// printk("=========>%s In\n", __FUNCTION__); ++ ++ //LeaveCallbackOfRtWorkItem( &(usbdevice->SwLed0WorkItem) ); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++void SwLed1WorkItemCallback(struct work_struct *work) ++{ ++ //struct r8180_priv *priv = container_of(work, struct r8180_priv, SwLed1WorkItem); ++// struct net_device *dev = priv->dev; ++#else ++void ++SwLed1WorkItemCallback( ++ void * Context ++ ) ++{ ++ //struct net_device *dev = (struct net_device *)Context; ++ //struct r8180_priv *priv = ieee80211_priv(dev); ++#endif ++// printk("=========>%s In\n", __FUNCTION__); ++ //SwLedBlink(dev, &(priv->SwLed1)); ++ ++ //LeaveCallbackOfRtWorkItem( &(usbdevice->SwLed1WorkItem) ); ++} ++ ++// ++// Implementation of LED blinking behavior. ++// It toggle off LED and schedule corresponding timer if necessary. ++// ++void ++SwLedBlink( ++ struct net_device *dev, ++ PLED_8187 pLed ++ ) ++{ ++ u8 bStopBlinking = 0; ++ ++ //printk("=========>%s In state:%d\n", __FUNCTION__, pLed->CurrLedState); ++ // Change LED according to BlinkingLedState specified. ++ if( pLed->BlinkingLedState == LED_ON ) ++ { ++ SwLedOn(dev, pLed); ++// printk("Blinktimes (%d): turn on\n", pLed->BlinkTimes); ++ } ++ else ++ { ++ SwLedOff(dev, pLed); ++// printk("Blinktimes (%d): turn off\n", pLed->BlinkTimes); ++ } ++ ++ // Determine if we shall change LED state again. ++//by lizhaoming for LED BLINK SLOWLY ++ if(pLed->CurrLedState == LED_BLINK_SLOWLY) ++ { ++ bStopBlinking = 0; ++ } else { ++ pLed->BlinkTimes--; ++ if( pLed->BlinkTimes == 0 ) ++ { ++ bStopBlinking = 1; ++ } ++ else ++ { ++ if( pLed->CurrLedState != LED_BLINK_NORMAL && ++ pLed->CurrLedState != LED_BLINK_SLOWLY && ++ pLed->CurrLedState != LED_BLINK_CM3 ) ++ { ++ bStopBlinking = 1; ++ } ++ } ++ } ++ ++ if(bStopBlinking) ++ { ++ if( pLed->CurrLedState == LED_ON && pLed->bLedOn == 0) ++ { ++ SwLedOn(dev, pLed); ++ } ++ else if(pLed->CurrLedState == LED_OFF && pLed->bLedOn == 1) ++ { ++ SwLedOff(dev, pLed); ++ } ++ ++ pLed->BlinkTimes = 0; ++ pLed->bLedBlinkInProgress = 0; ++ } ++ else ++ { ++ // Assign LED state to toggle. ++ if( pLed->BlinkingLedState == LED_ON ) ++ pLed->BlinkingLedState = LED_OFF; ++ else ++ pLed->BlinkingLedState = LED_ON; ++ ++ // Schedule a timer to toggle LED state. ++ switch( pLed->CurrLedState ) ++ { ++ case LED_BLINK_NORMAL: ++ //printk("LED_BLINK_NORMAL:Blinktimes (%d): turn off\n", pLed->BlinkTimes+1); ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_NORMAL_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); ++ break; ++ ++ case LED_BLINK_SLOWLY: ++ if( pLed->bLedOn == 1 ) ++ { ++ //printk("LED_BLINK_SLOWLY:turn off\n"); ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_SLOWLY_INTERVAL+50;//for pcie mini card spec page 33, 250ms ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL+50)); ++ pLed->BlinkingLedState = LED_OFF; ++ } else { ++ //printk("LED_BLINK_SLOWLY:turn on\n"); ++ //pLed->BlinkTimer.expires = jiffies + 5000;//for pcie mini card spec page 33, 5s ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(5000)); ++ pLed->BlinkingLedState = LED_ON; ++ } ++ break; ++ ++ case LED_BLINK_CM3: ++ //printk("LED_BLINK_CM3:Blinktimes (%d): turn off\n", pLed->BlinkTimes+1); ++ //pLed->BlinkTimer.expires = jiffies + LED_CM3_BLINK_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM3_BLINK_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_CM3_BLINK_INTERVAL); ++ break; ++ ++ default: ++ //printk("LED_BLINK_default:Blinktimes (%d): turn off\n", pLed->BlinkTimes+1); ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_SLOWLY_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); ++ break; ++ } ++ } ++} ++ ++ ++ ++// ++// Implementation of LED blinking behavior for SwLedControlMode2. ++// ++void ++SwLedCm2Blink( ++ struct net_device *dev, ++ PLED_8187 pLed ++ ) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ //PMGNT_INFO priv = &(dev->MgntInfo); ++ u8 bStopBlinking = 0; ++ ++ //printk("========+++++++++++++=>%s In\n", __FUNCTION__); ++ //To avoid LED blinking when rf is off, add by lizhaoming 2008.6.2 ++ if((priv->eRFPowerState == eRfOff) && (priv->RfOffReason>RF_CHANGE_BY_IPS)) ++ { ++ SwLedOff(dev, pLed); ++ ++ //pLed->BlinkTimer.expires = jiffies + LED_CM2_BLINK_ON_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL)); ++ //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_CM2_BLINK_ON_INTERVAL); ++ //printk(" Hw/Soft Radio Off, turn off Led\n"); ++ return; ++ } ++ ++ // Change LED according to BlinkingLedState specified. ++ if( pLed->BlinkingLedState == LED_ON ) ++ { ++ SwLedOn(dev, pLed); ++ //DMESG("Blinktimes (%d): turn on\n", pLed->BlinkTimes); ++ } ++ else ++ { ++ SwLedOff(dev, pLed); ++ //DMESG("Blinktimes (%d): turn off\n", pLed->BlinkTimes); ++ } ++ ++ //Add by lizhaoming for avoid BlinkTimers <0, 2008.6.2 ++ if(pLed->BlinkTimes > 0) ++ {//by lizhaoming 2008.6.2 ++ // Determine if we shall change LED state again. ++ pLed->BlinkTimes--; ++ }//by lizhaoming 2008.6.2 ++ ++ switch(pLed->CurrLedState) ++ { ++ case LED_BLINK_NORMAL: ++ if(pLed->BlinkTimes == 0) ++ { ++ bStopBlinking = 1; ++ } ++ break; ++/* CM2 scan blink and no link blind now not be supported ++ case LED_SCAN_BLINK: ++ if( (priv->mAssoc || priv->mIbss) && // Linked. ++ (!priv->bScanInProgress) && // Not in scan stage. ++ (pLed->BlinkTimes % 2 == 0)) // Even ++ { ++ bStopBlinking = 1; ++ } ++ break; ++ ++ case LED_NO_LINK_BLINK: ++ //Revised miniCard Ad-hoc mode "Slow Blink" by Isaiah 2006-08-03 ++ //if( (priv->mAssoc || priv->mIbss) ) // Linked. ++ if( priv->mAssoc) ++ { ++ bStopBlinking = 1; ++ } ++ else if(priv->mIbss && priv->bMediaConnect ) ++ { ++ bStopBlinking = 1; ++ } ++ break; ++*/ ++ default: ++ bStopBlinking = 1; ++ break; ++ } ++ ++ if(bStopBlinking) ++ { ++/* ++ if( priv->eRFPowerState != eRfOn ) ++ { ++ SwLedOff(dev, pLed); ++ } ++ else if( priv->bMediaConnect == 1 && pLed->bLedOn == 0) ++ { ++ SwLedOn(dev, pLed); ++ } ++ else if( priv->bMediaConnect == 0 && pLed->bLedOn == 1) ++ { ++ SwLedOff(dev, pLed); ++ } ++*/ ++ pLed->BlinkTimes = 0; ++ pLed->bLedBlinkInProgress = 0; ++ } ++ else ++ { ++ // Assign LED state to toggle. ++ if( pLed->BlinkingLedState == LED_ON ) ++ pLed->BlinkingLedState = LED_OFF; ++ else ++ pLed->BlinkingLedState = LED_ON; ++ ++ // Schedule a timer to toggle LED state. ++ switch( pLed->CurrLedState ) ++ { ++ case LED_BLINK_NORMAL: ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_NORMAL_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); ++ break; ++ ++ case LED_BLINK_SLOWLY: ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_SLOWLY_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); ++ break; ++ ++ case LED_SCAN_BLINK: ++ case LED_NO_LINK_BLINK: ++ if( pLed->bLedOn ) { ++ //pLed->BlinkTimer.expires = jiffies + LED_CM2_BLINK_ON_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_CM2_BLINK_ON_INTERVAL); ++ } else { ++ //pLed->BlinkTimer.expires = jiffies + LED_CM2_BLINK_OFF_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM2_BLINK_OFF_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_CM2_BLINK_OFF_INTERVAL); ++ } ++ break; ++ ++ default: ++ //RT_ASSERT(0, ("SwLedCm2Blink(): unexpected state!\n")); ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_SLOWLY_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL)); ++ //PlatformSetTimer(dev, &(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); ++ break; ++ } ++ } ++} ++ ++// added by lizhaoming 2008.6.2 ++// ++// Description: ++// Implement LED blinking behavior for SW_LED_MODE4. ++// ++void ++SwLedCm4Blink( ++ struct net_device *dev, ++ PLED_8187 pLed ++ ) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ u8 bStopBlinking = 0; ++ ++ printk("======++++++++++++++++++======>%s In\n", __FUNCTION__); ++ //To avoid LED blinking when rf is off, add by Maddest 20080307 ++ if((priv->eRFPowerState == eRfOff) && (priv->RfOffReason>RF_CHANGE_BY_IPS)) ++ { ++ SwLedOff(dev, pLed); ++ ++ //pLed->BlinkTimer.expires = jiffies + LED_CM4_BLINK_ON_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM4_BLINK_ON_INTERVAL)); ++ //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_CM4_BLINK_ON_INTERVAL); ++ printk(" Hw/Soft Radio Off, turn off Led\n"); ++ return; ++ } ++ // Change LED according to BlinkingLedState specified. ++ if( pLed->BlinkingLedState == LED_ON ) ++ { ++ if(!pLed->bLedOn) ++ { ++ SwLedOn(dev, pLed); ++ } ++ printk("Blinktimes (%d): turn on\n", pLed->BlinkTimes); ++ } ++ else ++ { ++ SwLedOff(dev, pLed); ++ printk("Blinktimes (%d): turn off\n", pLed->BlinkTimes); ++ } ++ ++ //Add by Maddest for avoid BlinkTimers <0, 20080307; ++ if(pLed->BlinkTimes > 0) ++ { ++ // Determine if we shall change LED state again. ++ pLed->BlinkTimes--; ++ } ++ printk("pLed->CurrLedState %d pLed->BlinkTimes %d\n", pLed->CurrLedState,pLed->BlinkTimes); ++ switch(pLed->CurrLedState) ++ { ++ case LED_BLINK_NORMAL: ++ if(pLed->BlinkTimes == 0) ++ { ++ bStopBlinking = 1; ++ } ++ break; ++ ++/* CM2 scan blink and no link blind now not be supported ++ case LED_SCAN_BLINK: ++ if( (priv->mAssoc || priv->mIbss) && // Linked.//???????????? ++ (!priv->bScanInProgress) && // Not in scan stage.//???????????? ++ (pLed->BlinkTimes % 2 == 0)) // Even ++ { ++ bStopBlinking = 1; ++ } ++ break; ++ ++ case LED_NO_LINK_BLINK: ++ //Revised miniCard Ad-hoc mode "Slow Blink" by Isaiah 2006-08-03 ++ //if( (pMgntInfo->mAssoc || pMgntInfo->mIbss) ) // Linked. ++ if( priv->mAssoc) //???????????? ++ { ++ bStopBlinking = 1; ++ } ++ else if(priv->mIbss && priv->bMediaConnect )//???????????? ++ { ++ bStopBlinking = 1; ++ } ++ break; ++*/ ++ ++ default: ++ bStopBlinking = 1; ++ break; ++ } ++ ++ if(bStopBlinking) ++ { ++ /* ++ if( priv->eRFPowerState != eRfOn ) ++ { ++ SwLedOff(dev, pLed); ++ } ++ else if( priv->bMediaConnect == true && pLed->bLedOn == false)//???????????? ++ { ++ SwLedOn(dev, pLed); ++ } ++ else if( priv->bMediaConnect == false && pLed->bLedOn == true)//???????????? ++ { ++ SwLedOff(dev, pLed); ++ } ++ */ ++ ++ pLed->BlinkTimes = 0; ++ pLed->bLedBlinkInProgress = 0; ++ } ++ else ++ { ++ // Assign LED state to toggle. ++ if( pLed->BlinkingLedState == LED_ON ) ++ pLed->BlinkingLedState = LED_OFF; ++ else ++ pLed->BlinkingLedState = LED_ON; ++ ++ // Schedule a timer to toggle LED state. ++ switch( pLed->CurrLedState ) ++ { ++ case LED_BLINK_NORMAL: ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_NORMAL_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); ++ //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); ++ break; ++ ++ case LED_BLINK_SLOWLY: ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_SLOWLY_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL)); ++ //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); ++ break; ++ ++ case LED_SCAN_BLINK: ++ pLed->BlinkingLedState = LED_ON; ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_NORMAL_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); ++ //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); ++ ++ case LED_NO_LINK_BLINK: ++ if( pLed->bLedOn ){ ++ //pLed->BlinkTimer.expires = jiffies + LED_CM4_BLINK_ON_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM4_BLINK_ON_INTERVAL)); ++ //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_CM4_BLINK_ON_INTERVAL); ++ }else{ ++ //pLed->BlinkTimer.expires = jiffies + LED_CM4_BLINK_OFF_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_CM4_BLINK_OFF_INTERVAL)); ++ //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_CM4_BLINK_OFF_INTERVAL); ++ } ++ break; ++ ++ default: ++ printk("SwLedCm2Blink(): unexpected state!\n"); ++ //pLed->BlinkTimer.expires = jiffies + LED_BLINK_SLOWLY_INTERVAL; ++ //add_timer(&(pLed->BlinkTimer)); ++ mod_timer(&pLed->BlinkTimer, jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL)); ++ //PlatformSetTimer(Adapter, &(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); ++ break; ++ } ++ } ++} ++ ++void ++SwLedOn( ++ struct net_device *dev, ++ PLED_8187 pLed ++) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++// printk("=========>%s(), pin:%d\n", __FUNCTION__, pLed->LedPin); ++ switch(pLed->LedPin) ++ { ++ case LED_PIN_GPIO0: ++ write_nic_byte(dev,0x0091,0x01); ++ write_nic_byte(dev,0x0090,0x00); // write 0 : LED on ++ break; ++ ++ case LED_PIN_LED0: ++ priv->PsrValue &= ~(0x01 << 4); ++ write_nic_byte(dev, PSR, priv->PsrValue); ++ break; ++ ++ case LED_PIN_LED1: ++ priv->PsrValue &= ~(0x01 << 5); ++ write_nic_byte(dev, PSR, priv->PsrValue); ++ break; ++ ++ default: ++ break; ++ } ++ ++ pLed->bLedOn = 1; ++} ++ ++void ++SwLedOff( ++ struct net_device *dev, ++ PLED_8187 pLed ++) ++{ ++ struct r8180_priv *priv = ieee80211_priv(dev); ++ ++ ++ //printk("=========>%s(), pin:%d\n", __FUNCTION__, pLed->LedPin); ++ switch(pLed->LedPin) ++ { ++ case LED_PIN_GPIO0: ++ write_nic_byte(dev,0x0091,0x01); ++ write_nic_byte(dev,0x0090,0x01); // write 1 : LED off ++ break; ++ ++ case LED_PIN_LED0: ++ priv->PsrValue |= (0x01 << 4); ++ write_nic_byte(dev, PSR, priv->PsrValue); ++ break; ++ ++ case LED_PIN_LED1: ++ priv->PsrValue |= (0x01 << 5); ++ write_nic_byte(dev, PSR, priv->PsrValue); ++ break; ++ ++ default: ++ break; ++ } ++ ++ pLed->bLedOn = 0; ++} ++ +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8187_led.h linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8187_led.h +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/r8187_led.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/r8187_led.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,276 @@ ++/*++ ++ ++Copyright (c) Microsoft Corporation. All rights reserved. ++ ++Module Name: ++ r8187_led.h ++ ++Abstract: ++ definitions and stuctures for rtl8187 led control. ++ ++Major Change History: ++ When Who What ++ ---------- ------ ---------------------------------------------- ++ 2006-09-07 Xiong Created ++ ++Notes: ++ ++--*/ ++ ++#ifndef R8187_LED_H ++#define R8187_LED_H ++ ++#include ++#include ++ ++ ++/*--------------------------Define -------------------------------------------*/ ++// ++// 0x7E-0x7F is reserved for SW customization. 2006.04.21, by rcnjko. ++// ++// BIT[0-7] is for CustomerID where value 0x00 and 0xFF is reserved for Realtek. ++#define EEPROM_SW_REVD_OFFSET 0x7E ++ ++#define EEPROM_CID_MASK 0x00FF ++#define EEPROM_CID_RSVD0 0x00 ++#define EEPROM_CID_RSVD1 0xFF ++#define EEPROM_CID_ALPHA0 0x01 ++#define EEPROM_CID_SERCOMM_PS 0x02 ++#define EEPROM_CID_HW_LED 0x03 ++ ++#define EEPROM_CID_QMI 0x07 //Added by lizhaoming 2008.6.3 ++#define EEPROM_CID_DELL 0x08 //Added by lizhaoming 2008.6.3 ++ ++#define LED_BLINK_NORMAL_INTERVAL 100 //by lizhaoming 50 -> 100 ++#define LED_BLINK_SLOWLY_INTERVAL 200 ++ ++// Customized for AzWave, 2006.04.03, by rcnjko. ++#define LED_CM2_BLINK_ON_INTERVAL 250 ++#define LED_CM2_BLINK_OFF_INTERVAL 4750 ++// ++ ++// Customized for Sercomm Printer Server case, 2006.04.21, by rcnjko. ++#define LED_CM3_BLINK_INTERVAL 1500 ++ ++// by lizhaoming 2008.6.3: Customized for QMI. ++// ++#define LED_CM4_BLINK_ON_INTERVAL 500 ++#define LED_CM4_BLINK_OFF_INTERVAL 4500 ++ ++ ++/*--------------------------Define MACRO--------------------------------------*/ ++ ++ ++/*------------------------------Define Struct---------------------------------*/ ++typedef enum _LED_STATE_8187{ ++ LED_UNKNOWN = 0, ++ LED_ON = 1, ++ LED_OFF = 2, ++ LED_BLINK_NORMAL = 3, ++ LED_BLINK_SLOWLY = 4, ++ LED_POWER_ON_BLINK = 5, ++ LED_SCAN_BLINK = 6, // LED is blinking during scanning period, the # of times to blink is depend on time for scanning. ++ LED_NO_LINK_BLINK = 7, // LED is blinking during no link state. ++ LED_BLINK_CM3 = 8, // Customzied for Sercomm Printer Server case ++}LED_STATE_8187; ++ ++typedef enum _RT_CID_TYPE { ++ RT_CID_DEFAULT, ++ RT_CID_8187_ALPHA0, ++ RT_CID_8187_SERCOMM_PS, ++ RT_CID_8187_HW_LED, ++ ++ RT_CID_87B_QMI , //Added by lizhaoming 2008.6.3 ++ RT_CID_87B_DELL, //Added by lizhaoming 2008.6.3 ++ ++} RT_CID_TYPE; ++ ++typedef enum _LED_STRATEGY_8187{ ++ SW_LED_MODE0, // SW control 1 LED via GPIO0. It is default option. ++ SW_LED_MODE1, // 2 LEDs, through LED0 and LED1. For ALPHA. ++ SW_LED_MODE2, // SW control 1 LED via GPIO0, customized for AzWave 8187 minicard. ++ SW_LED_MODE3, // SW control 1 LED via GPIO0, customized for Sercomm Printer Server case. ++ SW_LED_MODE4, //added by lizhaoming for bluetooth 2008.6.3 ++ SW_LED_MODE5, //added by lizhaoming for bluetooth 2008.6.3 ++ HW_LED, // HW control 2 LEDs, LED0 and LED1 (there are 4 different control modes, see MAC.CONFIG1 for details.) ++}LED_STRATEGY_8187, *PLED_STRATEGY_8187; ++ ++typedef enum _LED_PIN_8187{ ++ LED_PIN_GPIO0, ++ LED_PIN_LED0, ++ LED_PIN_LED1 ++}LED_PIN_8187; ++ ++//by lizhaoming for LED 2008.6.23 into ieee80211.h ++//typedef enum _LED_CTL_MODE { ++// LED_CTL_POWER_ON, ++// LED_CTL_POWER_OFF, ++// LED_CTL_LINK, ++// LED_CTL_NO_LINK, ++// LED_CTL_TX, ++// LED_CTL_RX, ++// LED_CTL_SITE_SURVEY, ++//} LED_CTL_MODE; ++ ++typedef struct _LED_8187{ ++ LED_PIN_8187 LedPin; // Identify how to implement this SW led. ++ ++ LED_STATE_8187 CurrLedState; // Current LED state. ++ u8 bLedOn; // TRUE if LED is ON, FALSE if LED is OFF. ++ ++ u8 bLedBlinkInProgress; // TRUE if it is blinking, FALSE o.w.. ++ u32 BlinkTimes; // Number of times to toggle led state for blinking. ++ LED_STATE_8187 BlinkingLedState; // Next state for blinking, either LED_ON or LED_OFF are. ++ struct timer_list BlinkTimer; // Timer object for led blinking. ++} LED_8187, *PLED_8187; ++ ++ ++ ++/*------------------------Export global variable------------------------------*/ ++ ++ ++/*------------------------------Funciton declaration--------------------------*/ ++void ++InitSwLeds( ++ struct net_device *dev ++ ); ++ ++void ++DeInitSwLeds( ++ struct net_device *dev ++ ); ++ ++void ++InitLed8187( ++ struct net_device *dev, ++ PLED_8187 pLed, ++ LED_PIN_8187 LedPin, ++ void * BlinkCallBackFunc); ++ ++void ++DeInitLed8187( ++ struct net_device *dev, ++ PLED_8187 pLed); ++ ++void ++LedControl8187( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++); ++ ++void ++SwLedControlMode0( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++); ++ ++void ++SwLedControlMode1( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++); ++ ++void ++SwLedControlMode2( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++); ++ ++void ++SwLedControlMode3( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++); ++ ++ ++void ++SwLedControlMode4( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++); ++ ++ ++void ++SwLedControlMode5( ++ struct net_device *dev, ++ LED_CTL_MODE LedAction ++); ++ ++void ++Gpio0LedBlinkTimerCallback( ++ unsigned long data ++ ); ++ ++void ++SwLed0BlinkTimerCallback( ++ unsigned long data ++ ); ++ ++void ++SwLed1BlinkTimerCallback( ++ unsigned long data ++ ); ++ ++void ++PlatformSwLedBlink( ++ struct net_device *dev, ++ PLED_8187 pLed ++ ); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++void ++Gpio0LedWorkItemCallback( ++ void * Context ++ ); ++ ++void ++SwLed0WorkItemCallback( ++ void * Context ++ ); ++ ++void ++SwLed1WorkItemCallback( ++ void * Context ++ ); ++#else ++void ++Gpio0LedWorkItemCallback(struct work_struct *work); ++ ++void ++SwLed0WorkItemCallback(struct work_struct *work); ++ ++void ++SwLed1WorkItemCallback(struct work_struct *work); ++ ++#endif ++void ++SwLedBlink( ++ struct net_device *dev, ++ PLED_8187 pLed ++ ); ++ ++void ++SwLedCm2Blink( ++ struct net_device *dev, ++ PLED_8187 pLed ++ ); ++ ++void ++SwLedCm4Blink( ++ struct net_device *dev, ++ PLED_8187 pLed ++ ); ++ ++void ++SwLedOn( ++ struct net_device *dev, ++ PLED_8187 pLed ++); ++ ++void ++SwLedOff( ++ struct net_device *dev, ++ PLED_8187 pLed ++); ++ ++ ++#endif +diff -Nur linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/readme linux-2.6.30.5/drivers/net/wireless/rtl8187b/readme +--- linux-2.6.30.5.orig/drivers/net/wireless/rtl8187b/readme 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/net/wireless/rtl8187b/readme 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,124 @@ ++rtl8187 Linux kernel driver ++Released under the terms of GNU General Public Licence (GPL) ++Copyright(c) Andrea Merello - 2004,2005 ++ ++Portions of this driver are based on other projects, please see the notes ++in the source files for detail. ++A special thanks go to Realtek corp for their support and to David Young ++------------------------------------------------------------------------------ ++ ++This is an attempt to write somethig that can make rtl8187 usb dongle wifi card ++on Linux using only opensource stuff. ++The rtl8225 radio is supported. ++ ++It's in early development stage so don't expect too much from it ++(also use it at your own risk!) ++This should be considered just a fragment of code.. using it on your(any) ++system is at your own risk! Please note that I never supported the idea to ++use it in any way, so i cannot be considered responsible in any way for ++anything deriving by it usage. ++ ++Anyway for now we have monitor mode and managed mode ++basically working! This isn't necessary stable, but seems to work.. ++ ++This driver is still under development and very far from perfect. It should work on x86, ++Other archs are untested.. ++ ++To compile the driver simply run make. ++ ++The driver contains also the ieee80211.h and ieee80211_crypt.h from the ieee stack. ++Note that for some reasons this stack is NOT the same that will be included in newer ++2.6 kernel. I will try to port to this stack as soon as it will have enought features ++to support 8187 cards. ++Please note that you will have to make sure the two .h files are the same of the ieee ++stack. ++In other words when you download from the CVS this driver and the ieee80211 stack a good ++idea is to copy the ieee80211.h and ieee80211_crypt.h from the ieee directory to the drv ++directory ++ ++Warning during compile are OK ++ ++To wake up the nic run: ++ ++ ifconfig up ++ ++(where is your network device for wlan card). ++ ++Please note that the default interface name is wlanX. ++ ++Please note thet this will take several seconds.. ++ ++If you would like to set the interface name to something else you may use the ++'devname=' module parameter. For example: ++ ++ insmod r8187.ko ifname=eth%d ++ ++will set the interface name of this device to something like eth0. ++ ++Once the nic is up it can be put in a monitor mode by running: ++ ++ iwconfig mode monitor ++ ++and channel number may be changed by running: ++ ++ iwconfig channel XX ++ ++ ++In monitor mode a choice may be made via iwpriv if the nic should pass packets ++with bad crc or drop them. ++ ++To put the nic in managed mode run: ++ ++ iwconfig mode managed ++ ++In managed mode there is support for ++ ++ iwlist scan ++ ++that should report the currently available networks. ++Please note that in managed mode channels cannot be changed manually. ++ ++To associate with a network ++ ++ iwconfig essid XXXXX ++ ++where XXXXX is the network essid (name) reported by 'iwlist scan'. Please ++note that essid is case sensitive. ++ ++If your network is not broadcasting the ESSID, then you need to specify *also* ++the AP MAC address ++ ++ iwconfig ap XX:XX:XX:XX:XX:XX ++ ++The driver accepts another boolean parameter: hwseqnum ++If set to 1 it lets the card HW take care of the sequence number of the TXed ++frames. Altought in managed mode I can't see an important reason to use HW to ++do that, when we'll start to TX beacons in master (AP) and ad-hoc modes most ++probably it will be extremely useful (since most probably we will use two HW ++queues). ++ ++I'm unsure if it will work correctly on all NICs.. reports are *VERY, VERY* apreciated.. ++ ++ ++ WEP ++ === ++ ++WEP encryption should work. For now it's done by host, not by the nic. Key can be set with: ++Key can be set with ++ ++ iwconfig key 12345... ++ ++WEP is supported via software thanks to the ipw stack. ++ ++Shared and open authentication are supported ++ ++ IWPRIV ++ ====== ++ ++This driver supports some private handlers: ++-badcrc: let you choose to kill or to pass to the upper layer frames with bad crc in monitor mode ++-activescan: if 0 the driver will avoid to send probe requests, sanning will be only on beacon basis ++ ++ ++If you have some question/comments please feel free to write me. ++ +diff -Nur linux-2.6.30.5.orig/drivers/platform/Kconfig linux-2.6.30.5/drivers/platform/Kconfig +--- linux-2.6.30.5.orig/drivers/platform/Kconfig 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/drivers/platform/Kconfig 2009-08-21 21:18:15.000000000 +0200 +@@ -3,3 +3,7 @@ + if X86 + source "drivers/platform/x86/Kconfig" + endif ++ ++if MACH_LOONGSON ++source "drivers/platform/loongson/Kconfig" ++endif +diff -Nur linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec_bat.c linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec_bat.c +--- linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec_bat.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec_bat.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,388 @@ ++/* ++ * EC(Embedded Controller) KB3310B battery management driver on Linux ++ * ++ * Author: liujl ++ * Date : 2008-03-17 ++ * ++ * NOTE: The SDA0/SCL0 in KB3310B are used to communicate with the battery ++ * IC, Here we use DS2786 IC to handle the battery management. All the ++ * resources for handle battery management in KB3310B are: ++ * 1, one SMBus interface with port 0 ++ * 2, gpio40 output for charge enable ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "ec.h" ++#include "ec_misc_fn.h" ++ ++#ifndef APM_32_BIT_SUPPORT ++#define APM_32_BIT_SUPPORT 0x0002 ++#endif ++ ++/* The EC Battery device, here is his minor number. */ ++#define ECBAT_MINOR_DEV MISC_DYNAMIC_MINOR ++ ++/* ++ * apm threshold : percent unit. ++ */ ++#define BAT_MAX_THRESHOLD 99 ++#define BAT_MIN_THRESHOLD 5 ++ ++/* ++ * This structure gets filled in by the machine specific 'get_power_status' ++ * implementation. Any fields which are not set default to a safe value. ++ */ ++struct apm_pwr_info { ++ unsigned char ac_line_status; ++#define APM_AC_OFFLINE 0 ++#define APM_AC_ONLINE 1 ++#define APM_AC_BACKUP 2 ++#define APM_AC_UNKNOWN 0xff ++ ++ unsigned char battery_status; ++#define APM_BATTERY_STATUS_HIGH 0 ++#define APM_BATTERY_STATUS_LOW 1 ++#define APM_BATTERY_STATUS_CRITICAL 2 ++#define APM_BATTERY_STATUS_CHARGING 3 ++#define APM_BATTERY_STATUS_NOT_PRESENT 4 ++#define APM_BATTERY_STATUS_UNKNOWN 0xff ++ ++ unsigned char battery_flag; ++#define APM_BATTERY_FLAG_HIGH (1 << 0) ++#define APM_BATTERY_FLAG_LOW (1 << 1) ++#define APM_BATTERY_FLAG_CRITICAL (1 << 2) ++#define APM_BATTERY_FLAG_CHARGING (1 << 3) ++#define APM_BATTERY_FLAG_NOT_PRESENT (1 << 7) ++#define APM_BATTERY_FLAG_UNKNOWN 0xff ++ ++ int battery_life; ++ int time; ++ int units; ++#define APM_UNITS_MINS 0 ++#define APM_UNITS_SECS 1 ++#define APM_UNITS_UNKNOWN -1 ++ ++ /* battery designed capacity */ ++ unsigned int bat_design_cap; ++ /* battery designed voltage */ ++ unsigned int bat_design_vol; ++ /* battery capacity after full charged */ ++ unsigned int bat_full_charged_cap; ++ /* battery vendor number */ ++ unsigned char bat_vendor; ++ /* battery cell count */ ++ unsigned char bat_cell_count; ++ ++ /* battery dynamic charge/discharge voltage */ ++ unsigned int bat_voltage; ++ /* battery dynamic charge/discharge current */ ++ int bat_current; ++ /* battery current temperature */ ++ unsigned int bat_temperature; ++}; ++ ++static struct task_struct *battery_tsk; ++ ++static DEFINE_MUTEX(bat_info_lock); ++struct bat_info { ++ unsigned int ac_in; ++ unsigned int bat_in; ++ unsigned int bat_flag; ++ /* we use capacity for caculating the life and time */ ++ unsigned int curr_bat_cap; ++ ++ /* battery designed capacity */ ++ unsigned int bat_design_cap; ++ /* battery designed voltage */ ++ unsigned int bat_design_vol; ++ /* battery capacity after full charged */ ++ unsigned int bat_full_charged_cap; ++ /* battery vendor number */ ++ unsigned char bat_vendor; ++ /* battery cell count */ ++ unsigned char bat_cell_count; ++ ++ /* battery dynamic charge/discharge voltage */ ++ unsigned int bat_voltage; ++ /* battery dynamic charge/discharge current */ ++ int bat_current; ++ /* battery current temperature */ ++ unsigned int bat_temperature; ++} bat_info = { ++ .ac_in = APM_AC_UNKNOWN, ++ .bat_in = APM_BATTERY_STATUS_UNKNOWN, ++ .curr_bat_cap = 0, ++ /* fixed value */ ++ .bat_design_cap = 0, ++ .bat_full_charged_cap = 0, ++ .bat_design_vol = 0, ++ .bat_vendor = 0, ++ .bat_cell_count = 0, ++ /* rest variable */ ++ .bat_voltage = 0, ++ .bat_current = 0, ++ .bat_temperature = 0 ++}; ++ ++/* ++ * 1.4 : ++ * 1, 89inch basic work version. ++ * 2, you should set xorg.conf ServerFlag of "NoPM" to true ++ * 1.5 : ++ * 1, bat_flag is added to struct bat_info. ++ * 2, BAT_MIN_THRESHOLD is changed to 5%. ++ */ ++static const char driver_version[] = VERSION; /* no spaces */ ++ ++static struct miscdevice apm_device = { ++ .minor = ECBAT_MINOR_DEV, ++ .name = "apm_bios", ++ .fops = NULL ++}; ++ ++#ifdef CONFIG_PROC_FS ++static int bat_proc_read(char *page, char **start, off_t off, int count, ++ int *eof, void *data); ++static struct proc_dir_entry *bat_proc_entry; ++ ++static int bat_proc_read(char *page, char **start, off_t off, int count, ++ int *eof, void *data) ++{ ++ struct apm_pwr_info info; ++ char *units; ++ int ret; ++ ++ mutex_lock(&bat_info_lock); ++ info.battery_life = bat_info.curr_bat_cap; ++ info.ac_line_status = bat_info.ac_in; ++ info.battery_status = bat_info.bat_in; ++ info.battery_flag = bat_info.bat_flag; ++ info.bat_voltage = bat_info.bat_voltage; ++ if (bat_info.bat_current & 0x8000) ++ info.bat_current = 0xffff - bat_info.bat_current; ++ else ++ info.bat_current = bat_info.bat_current; ++ info.bat_temperature = bat_info.bat_temperature; ++ ++ /* this should be charged according to the capacity-time flow. */ ++ if (info.battery_status != APM_BATTERY_STATUS_NOT_PRESENT) ++ info.time = ((bat_info.curr_bat_cap - 3) * 54 + 142) / 60; ++ else ++ info.time = 0x00; ++ info.units = APM_UNITS_MINS; ++ ++ mutex_unlock(&bat_info_lock); ++ switch (info.units) { ++ default: ++ units = "?"; ++ break; ++ case 0: ++ units = "min"; ++ break; ++ case 1: ++ units = "sec"; ++ break; ++ } ++ ++ ret = ++ sprintf(page, ++ "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s %dmV %dmA %d\n", ++ driver_version, APM_32_BIT_SUPPORT, info.ac_line_status, ++ info.battery_status, info.battery_flag, info.battery_life, ++ info.time, units, info.bat_voltage, info.bat_current, ++ info.bat_temperature); ++ ++ ret -= off; ++ if (ret < off + count) ++ *eof = 1; ++ *start = page + off; ++ if (ret > count) ++ ret = count; ++ if (ret < 0) ++ ret = 0; ++ ++ return ret; ++} ++#endif ++ ++static int battery_manager(void *arg) ++{ ++ unsigned char bat_charge; ++ unsigned char power_flag; ++ unsigned char bat_status; ++ unsigned char charge_status; ++ ++ /* read out the fixed value */ ++ bat_info.bat_design_cap = (ec_read(REG_BAT_DESIGN_CAP_HIGH) << 8) ++ | ec_read(REG_BAT_DESIGN_CAP_LOW); ++ bat_info.bat_full_charged_cap = (ec_read(REG_BAT_FULLCHG_CAP_HIGH) << 8) ++ | ec_read(REG_BAT_FULLCHG_CAP_LOW); ++ bat_info.bat_design_vol = (ec_read(REG_BAT_DESIGN_VOL_HIGH) << 8) ++ | ec_read(REG_BAT_DESIGN_VOL_LOW); ++ bat_info.bat_vendor = ec_read(REG_BAT_VENDOR); ++ bat_info.bat_cell_count = ec_read(REG_BAT_CELL_COUNT); ++ if (bat_info.bat_vendor != 0) { ++ printk(KERN_INFO ++ "battery vendor(%s), cells count(%d), " ++ "with designed capacity(%d),designed voltage(%d)," ++ " full charged capacity(%d)\n", ++ (bat_info.bat_vendor == ++ FLAG_BAT_VENDOR_SANYO) ? "SANYO" : "SIMPLO", ++ (bat_info.bat_cell_count == FLAG_BAT_CELL_3S1P) ? 3 : 6, ++ bat_info.bat_design_cap, bat_info.bat_design_vol, ++ bat_info.bat_full_charged_cap); ++ } ++ ++ PRINTK_DBG(KERN_DEBUG "Battery manager thread started.\n"); ++ while (1) { ++ set_current_state(TASK_INTERRUPTIBLE); ++ /* schedule every 1s, it is better for changed to 1s. */ ++ schedule_timeout(HZ * 1); ++ ++ if (kthread_should_stop()) ++ break; ++ ++ mutex_lock(&bat_info_lock); ++ ++ bat_charge = ec_read(REG_BAT_CHARGE); ++ power_flag = ec_read(REG_BAT_POWER); ++ bat_status = ec_read(REG_BAT_STATUS); ++ charge_status = ec_read(REG_BAT_CHARGE_STATUS); ++ bat_info.bat_voltage = ++ (ec_read(REG_BAT_VOLTAGE_HIGH) << 8) | ++ (ec_read(REG_BAT_VOLTAGE_LOW)); ++ bat_info.bat_current = ++ (ec_read(REG_BAT_CURRENT_HIGH) << 8) | ++ (ec_read(REG_BAT_CURRENT_LOW)); ++ bat_info.bat_temperature = ++ (ec_read(REG_BAT_TEMPERATURE_HIGH) << 8) | ++ (ec_read(REG_BAT_TEMPERATURE_LOW)); ++ bat_info.curr_bat_cap = ++ (ec_read(REG_BAT_RELATIVE_CAP_HIGH) << 8) | ++ (ec_read(REG_BAT_RELATIVE_CAP_LOW)); ++ ++ bat_info.ac_in = ++ (power_flag & BIT_BAT_POWER_ACIN) ? APM_AC_ONLINE : ++ APM_AC_OFFLINE; ++ if (!(bat_status & BIT_BAT_STATUS_IN)) { ++ /* there is no battery inserted */ ++ bat_info.bat_in = APM_BATTERY_STATUS_NOT_PRESENT; ++ bat_info.bat_flag = APM_BATTERY_FLAG_NOT_PRESENT; ++ } else { ++ /* there is adapter inserted */ ++ if (bat_info.ac_in == APM_AC_ONLINE) { ++ /* if the battery is not fully charged */ ++ if (!(bat_status & BIT_BAT_STATUS_FULL)) { ++ bat_info.bat_in = ++ APM_BATTERY_STATUS_CHARGING; ++ bat_info.bat_flag = ++ APM_BATTERY_FLAG_CHARGING; ++ } else { ++ /* if the battery is fully charged */ ++ bat_info.bat_in = ++ APM_BATTERY_STATUS_HIGH; ++ bat_info.bat_flag = ++ APM_BATTERY_FLAG_HIGH; ++ bat_info.curr_bat_cap = 100; ++ } ++ } else { ++ /* if the battery is too low */ ++ if (bat_status & BIT_BAT_STATUS_LOW) { ++ bat_info.bat_in = ++ APM_BATTERY_STATUS_LOW; ++ bat_info.bat_flag = ++ APM_BATTERY_FLAG_LOW; ++ if (bat_info.curr_bat_cap <= ++ BAT_MIN_THRESHOLD) { ++ bat_info.bat_in = ++ APM_BATTERY_STATUS_CRITICAL; ++ bat_info.bat_flag = ++ APM_BATTERY_FLAG_CRITICAL; ++ } ++ /* we should power off the system now */ ++ } else { ++ /* assume the battery is high enough. */ ++ bat_info.bat_in = ++ APM_BATTERY_STATUS_HIGH; ++ bat_info.bat_flag = ++ APM_BATTERY_FLAG_HIGH; ++ } ++ } ++ } ++ mutex_unlock(&bat_info_lock); ++ } ++ ++ PRINTK_DBG(KERN_DEBUG "Battery Management thread exit.\n"); ++ return 0; ++} ++ ++static int __init apm_init(void) ++{ ++ int ret; ++ ++ printk(KERN_ERR ++ "APM of battery on KB3310B Embedded Controller init.\n"); ++ ++ battery_tsk = kthread_create(battery_manager, NULL, "battery_manager"); ++ if (IS_ERR(battery_tsk)) { ++ ret = PTR_ERR(battery_tsk); ++ kthread_stop(battery_tsk); ++ battery_tsk = NULL; ++ printk(KERN_ERR "ecbat : battery management error.\n"); ++ return ret; ++ } ++ battery_tsk->flags |= PF_NOFREEZE; ++ wake_up_process(battery_tsk); ++ ++#ifdef CONFIG_PROC_FS ++ bat_proc_entry = NULL; ++ bat_proc_entry = create_proc_entry("apm", S_IWUSR | S_IRUGO, NULL); ++ if (bat_proc_entry == NULL) { ++ printk(KERN_ERR "EC BAT : register /proc/apm failed.\n"); ++ return -EINVAL; ++ } ++ bat_proc_entry->read_proc = bat_proc_read; ++ bat_proc_entry->write_proc = NULL; ++ bat_proc_entry->data = NULL; ++#endif ++ ++ ret = misc_register(&apm_device); ++ if (ret != 0) { ++ remove_proc_entry("apm", NULL); ++ kthread_stop(battery_tsk); ++ printk(KERN_ERR "ecbat : misc register error.\n"); ++ } ++ return ret; ++} ++ ++static void __exit apm_exit(void) ++{ ++ misc_deregister(&apm_device); ++#ifdef CONFIG_PROC_FS ++ remove_proc_entry("apm", NULL); ++#endif ++ kthread_stop(battery_tsk); ++} ++ ++module_init(apm_init); ++module_exit(apm_exit); ++ ++MODULE_AUTHOR("liujl "); ++MODULE_DESCRIPTION("Advanced Power Management For Kb3310"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec_ft.c linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec_ft.c +--- linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec_ft.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec_ft.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,216 @@ +/* -+ * Function to queue the packet for the Ethernet device ++ * EC(Embedded Controller) KB3310B Fan and Temperature management driver on ++ * Linux ++ * ++ * Author: liujl ++ * Date : 2008-06-23 ++ * ++ * NOTE: The SDA1/SCL1 in KB3310B are used to communicate with the ++ * Temperature IC, Here we use ADT75 IC to handle the temperature management. ++ * and the Fan is controller by ADT75AZ, but the status is reflected to the ++ * KB3310 FANFB All the resources for handle battery management in KB3310B: ++ * 1, one SMBus interface with port 1 ++ * 2, gpio14 input alternate for FANFB + */ -+static void titan_ge_tx_queue(titan_ge_port_info * titan_ge_eth, -+ struct sk_buff * skb) ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ec.h" ++#include "ec_misc_fn.h" ++ ++#define EC_FT_DEV "ft" ++/* The EC Battery device is one of the misc device, here is his minor number. */ ++#define ECFT_MINOR_DEV MISC_DYNAMIC_MINOR ++#define PROC_FT_DIR "ft" ++ ++static struct task_struct *ft_tsk; ++static DEFINE_MUTEX(ft_info_lock); ++ ++/* driver version */ ++static const char driver_version[] = VERSION; ++ ++/* fan speed divider */ ++#define FAN_SPEED_DIVIDER 480000 /* (60*1000*1000/62.5/2)*/ ++ ++/* fan status : on or off */ ++#define FAN_STATUS_ON 0x01 ++#define FAN_STATUS_OFF 0x00 ++/* fan is not running */ ++#define FAN_SPEED_NONE 0x00 ++/* temperature negative or positive */ ++#define TEMPERATURE_POSITIVE 0x00 ++#define TEMPERATURE_NEGATIVE 0x01 ++/* temperature value is zero */ ++#define TEMPERATURE_NONE 0x00 ++struct ft_info { ++ u8 fan_on; ++ u16 fan_speed; ++ u8 temperature_pn; ++ u8 temperature; ++} ft_info = { ++ .fan_on = FAN_STATUS_ON, ++ .fan_speed = FAN_SPEED_NONE, ++ .temperature_pn = TEMPERATURE_POSITIVE, ++ .temperature = TEMPERATURE_NONE ++}; ++ ++static struct miscdevice ft_device = { ++ .minor = ECFT_MINOR_DEV, ++ .name = EC_FT_DEV, ++ .fops = NULL ++}; ++ ++#ifdef CONFIG_PROC_FS ++static int ft_proc_read(char *page, char **start, off_t off, int count, ++ int *eof, void *data); ++static struct proc_dir_entry *ft_proc_entry; ++ ++static int ft_proc_read(char *page, char **start, off_t off, int count, ++ int *eof, void *data) ++{ ++ struct ft_info info; ++ int ret; ++ ++ mutex_lock(&ft_info_lock); ++ info.fan_on = ft_info.fan_on; ++ if (info.fan_on == FAN_STATUS_ON) ++ info.fan_speed = ft_info.fan_speed; ++ else ++ info.fan_speed = 0x00; ++ info.temperature_pn = ft_info.temperature_pn; ++ info.temperature = ft_info.temperature; ++ mutex_unlock(&ft_info_lock); ++ ++ ret = ++ sprintf(page, "%s 0x%02x %d 0x%02x %d\n", driver_version, ++ info.fan_on, info.fan_speed, info.temperature_pn, ++ info.temperature); ++ ++ ret -= off; ++ if (ret < off + count) ++ *eof = 1; ++ ++ *start = page + off; ++ if (ret > count) ++ ret = count; ++ if (ret < 0) ++ ret = 0; ++ ++ return ret; ++} ++#endif ++ ++static int ft_manager(void *arg) ++{ ++ u8 val, reg_val; ++ ++ PRINTK_DBG(KERN_DEBUG "Fan & Temperature Management thread started.\n"); ++ while (1) { ++ set_current_state(TASK_INTERRUPTIBLE); ++ /* schedule every 1s */ ++ schedule_timeout(HZ); /* 1s */ ++ ++ if (kthread_should_stop()) ++ break; ++ ++ mutex_lock(&ft_info_lock); ++ ++ val = ec_read(REG_FAN_STATUS); ++ ft_info.fan_speed = ++ FAN_SPEED_DIVIDER / ++ (((ec_read(REG_FAN_SPEED_HIGH) & 0x0f) << 8) | ++ ec_read(REG_FAN_SPEED_LOW)); ++ reg_val = ec_read(REG_TEMPERATURE_VALUE); ++ ++ if (val) ++ ft_info.fan_on = FAN_STATUS_ON; ++ else ++ ft_info.fan_on = FAN_STATUS_OFF; ++ ++ if (reg_val & (1 << 7)) { ++ ft_info.temperature = (reg_val & 0x7f) - 128; ++ ft_info.temperature_pn = TEMPERATURE_NEGATIVE; ++ } else { ++ ft_info.temperature = (reg_val & 0xff); ++ ft_info.temperature_pn = TEMPERATURE_POSITIVE; ++ } ++ mutex_unlock(&ft_info_lock); ++ } ++ ++ PRINTK_DBG(KERN_DEBUG "Fan and Temperature Management thread exit.\n"); ++ ++ return 0; ++ ++} ++ ++static int __init ft_init(void) ++{ ++ int ret; ++ ++ printk(KERN_INFO ++ "Fan and Temperature on KB3310B Embedded Controller init.\n"); ++ ft_tsk = kthread_create(ft_manager, NULL, "ft_manager"); ++ if (IS_ERR(ft_tsk)) { ++ ret = PTR_ERR(ft_tsk); ++ kthread_stop(ft_tsk); ++ ft_tsk = NULL; ++ printk(KERN_ERR "ecft : ft management error.\n"); ++ return ret; ++ } ++ ft_tsk->flags |= PF_NOFREEZE; ++ wake_up_process(ft_tsk); ++ ++#ifdef CONFIG_PROC_FS ++ ft_proc_entry = NULL; ++ ft_proc_entry = create_proc_entry(EC_FT_DEV, S_IWUSR | S_IRUGO, NULL); ++ if (ft_proc_entry == NULL) { ++ printk(KERN_ERR "EC FT : register /proc/ft failed.\n"); ++ return -EINVAL; ++ } ++ ft_proc_entry->read_proc = ft_proc_read; ++ ft_proc_entry->write_proc = NULL; ++ ft_proc_entry->data = NULL; ++#endif ++ ++ ret = misc_register(&ft_device); ++ if (ret != 0) { ++#ifdef CONFIG_PROC_FS ++ remove_proc_entry(EC_FT_DEV, NULL); ++#endif ++ kthread_stop(ft_tsk); ++ printk(KERN_ERR "ecft : fan&temperature register error.\n"); ++ } ++ ++ return ret; ++} ++ ++static void __exit ft_exit(void) +{ -+ struct device *device = &titan_ge_device[titan_ge_eth->port_num]->dev; -+ unsigned int curr_desc = titan_ge_eth->tx_curr_desc_q; -+ volatile titan_ge_tx_desc *tx_curr; -+ int port_num = titan_ge_eth->port_num; ++ misc_deregister(&ft_device); ++#ifdef CONFIG_PROC_FS ++ remove_proc_entry(EC_FT_DEV, NULL); ++#endif ++ kthread_stop(ft_tsk); ++} ++ ++module_init(ft_init); ++module_exit(ft_exit); ++ ++MODULE_AUTHOR("liujl "); ++MODULE_DESCRIPTION("Advanced Fan and Temperature Management For Kb3310"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec.h linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec.h +--- linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,218 @@ ++/* ++ * EC(Embedded Controller) KB3310B misc device driver header for Linux ++ * Author: liujl ++ * Date : 2008-03-14 ++ * ++ * EC relative header file. All the EC registers should be defined here. ++ */ ++ ++#include ++#include ++#include ++ ++#define VERSION "1.37" ++ ++/* ++ * The following registers are determined by the EC index configuration. ++ * 1, fill the PORT_HIGH as EC register high part. ++ * 2, fill the PORT_LOW as EC register low part. ++ * 3, fill the PORT_DATA as EC register write data or get the data from it. ++ */ ++#define EC_IO_PORT_HIGH 0x0381 ++#define EC_IO_PORT_LOW 0x0382 ++#define EC_IO_PORT_DATA 0x0383 ++ ++/* ec registers range */ ++#define EC_MAX_REGADDR 0xFFFF ++#define EC_MIN_REGADDR 0xF000 ++/* #define EC_RAM_ADDR 0xF400 */ ++#define EC_RAM_ADDR 0xF800 ++ ++/* temperature & fan registers */ ++#define REG_TEMPERATURE_VALUE 0xF458 /* current temperature value */ ++#define REG_FAN_CONTROL 0xF4D2 /* fan control */ ++#define BIT_FAN_CONTROL_ON (1 << 0) ++#define BIT_FAN_CONTROL_OFF (0 << 0) ++#define REG_FAN_STATUS 0xF4DA /* fan status */ ++#define BIT_FAN_STATUS_ON (1 << 0) ++#define BIT_FAN_STATUS_OFF (0 << 0) ++#define REG_FAN_SPEED_HIGH 0xFE22 /* fan speed high byte */ ++#define REG_FAN_SPEED_LOW 0xFE23 /* fan speed low byte */ ++#define REG_FAN_SPEED_LEVEL 0xF4E4 /* fan speed level, from 1 to 5 */ ++ ++/* battery registers */ ++#define REG_BAT_DESIGN_CAP_HIGH 0xF77D /* design capacity high byte */ ++#define REG_BAT_DESIGN_CAP_LOW 0xF77E /* design capacity low byte */ ++#define REG_BAT_FULLCHG_CAP_HIGH 0xF780 /* full charged capacity high byte */ ++#define REG_BAT_FULLCHG_CAP_LOW 0xF781 /* full charged capacity low byte */ ++#define REG_BAT_DESIGN_VOL_HIGH 0xF782 /* design voltage high byte */ ++#define REG_BAT_DESIGN_VOL_LOW 0xF783 /* design voltage low byte */ ++#define REG_BAT_CURRENT_HIGH 0xF784 /* battery in/out current high byte */ ++#define REG_BAT_CURRENT_LOW 0xF785 /* battery in/out current low byte */ ++#define REG_BAT_VOLTAGE_HIGH 0xF786 /* battery current voltage high byte */ ++#define REG_BAT_VOLTAGE_LOW 0xF787 /* battery current voltage low byte */ ++#define REG_BAT_TEMPERATURE_HIGH 0xF788 /* battery current temperature high byte */ ++#define REG_BAT_TEMPERATURE_LOW 0xF789 /* battery current temperature low byte */ ++#define REG_BAT_RELATIVE_CAP_HIGH 0xF492 /* relative capacity high byte */ ++#define REG_BAT_RELATIVE_CAP_LOW 0xF493 /* relative capacity low byte */ ++#define REG_BAT_VENDOR 0xF4C4 /* battery vendor number */ ++#define FLAG_BAT_VENDOR_SANYO 0x01 ++#define FLAG_BAT_VENDOR_SIMPLO 0x02 ++#define REG_BAT_CELL_COUNT 0xF4C6 /* how many cells in one battery */ ++#define FLAG_BAT_CELL_3S1P 0x03 ++#define FLAG_BAT_CELL_3S2P 0x06 ++#define REG_BAT_CHARGE 0xF4A2 /* macroscope battery charging */ ++#define FLAG_BAT_CHARGE_DISCHARGE 0x01 ++#define FLAG_BAT_CHARGE_CHARGE 0x02 ++#define FLAG_BAT_CHARGE_ACPOWER 0x00 ++#define REG_BAT_STATUS 0xF4B0 ++#define BIT_BAT_STATUS_LOW (1 << 5) ++#define BIT_BAT_STATUS_DESTROY (1 << 2) ++#define BIT_BAT_STATUS_FULL (1 << 1) ++#define BIT_BAT_STATUS_IN (1 << 0) ++#define REG_BAT_CHARGE_STATUS 0xF4B1 ++#define BIT_BAT_CHARGE_STATUS_OVERTEMP (1 << 2) /* over temperature */ ++#define BIT_BAT_CHARGE_STATUS_PRECHG (1 << 1) /* pre-charge the battery */ ++#define REG_BAT_STATE 0xF482 ++#define BIT_BAT_STATE_CHARGING (1 << 1) ++#define BIT_BAT_STATE_DISCHARGING (1 << 0) ++#define REG_BAT_POWER 0xF440 ++#define BIT_BAT_POWER_S3 (1 << 2) /* enter s3 standby mode */ ++#define BIT_BAT_POWER_ON (1 << 1) /* system is on */ ++#define BIT_BAT_POWER_ACIN (1 << 0) /* adapter is inserted */ ++ ++/* other registers */ ++#define REG_AUDIO_MUTE 0xF4E7 /* audio mute : rd/wr */ ++#define BIT_AUDIO_MUTE_ON (1 << 0) ++#define BIT_AUDIO_MUTE_OFF (0 << 0) ++#define REG_AUDIO_BEEP 0xF4D0 /* audio beep and reset : rd/wr */ ++#define BIT_AUDIO_BEEP_ON (1 << 0) ++#define BIT_AUDIO_BEEP_OFF (0 << 0) ++#define REG_USB0_FLAG 0xF461 /* usb0 port power or not : rd/wr */ ++#define BIT_USB0_FLAG_ON (1 << 0) ++#define BIT_USB0_FLAG_OFF (0 << 0) ++#define REG_USB1_FLAG 0xF462 /* usb1 port power or not : rd/wr */ ++#define BIT_USB1_FLAG_ON (1 << 0) ++#define BIT_USB1_FLAG_OFF (0 << 0) ++#define REG_USB2_FLAG 0xF463 /* usb2 port power or not : rd/wr */ ++#define BIT_USB2_FLAG_ON (1 << 0) ++#define BIT_USB2_FLAG_OFF (0 << 0) ++#define REG_CRT_DETECT 0xF4AD /* detected CRT exist or not */ ++#define BIT_CRT_DETECT_PLUG (1 << 0) ++#define BIT_CRT_DETECT_UNPLUG (0 << 0) ++#define REG_LID_DETECT 0xF4BD /* detected LID is on or not */ ++#define BIT_LID_DETECT_ON (1 << 0) ++#define BIT_LID_DETECT_OFF (0 << 0) ++#define REG_RESET 0xF4EC /* reset the machine auto-clear : rd/wr */ ++#define BIT_RESET_ON (1 << 0) ++#define BIT_RESET_OFF (0 << 0) ++#define REG_LED 0xF4C8 /* light the led : rd/wr */ ++#define BIT_LED_RED_POWER (1 << 0) ++#define BIT_LED_ORANGE_POWER (1 << 1) ++#define BIT_LED_GREEN_CHARGE (1 << 2) ++#define BIT_LED_RED_CHARGE (1 << 3) ++#define BIT_LED_NUMLOCK (1 << 4) ++#define REG_LED_TEST 0xF4C2 /* test led mode, all led on or off */ ++#define BIT_LED_TEST_IN (1 << 0) ++#define BIT_LED_TEST_OUT (0 << 0) ++#define REG_DISPLAY_BRIGHTNESS 0xF4F5 /* 9 stages LCD backlight brightness adjust */ ++#define FLAG_DISPLAY_BRIGHTNESS_LEVEL_0 0 ++#define FLAG_DISPLAY_BRIGHTNESS_LEVEL_1 1 ++#define FLAG_DISPLAY_BRIGHTNESS_LEVEL_2 2 ++#define FLAG_DISPLAY_BRIGHTNESS_LEVEL_3 3 ++#define FLAG_DISPLAY_BRIGHTNESS_LEVEL_4 4 ++#define FLAG_DISPLAY_BRIGHTNESS_LEVEL_5 5 ++#define FLAG_DISPLAY_BRIGHTNESS_LEVEL_6 6 ++#define FLAG_DISPLAY_BRIGHTNESS_LEVEL_7 7 ++#define FLAG_DISPLAY_BRIGHTNESS_LEVEL_8 8 ++#define REG_CAMERA_STATUS 0xF46A /* camera is in ON/OFF status. */ ++#define BIT_CAMERA_STATUS_ON (1 << 0) ++#define BIT_CAMERA_STATUS_OFF (0 << 0) ++#define REG_CAMERA_CONTROL 0xF7B7 /* control camera to ON/OFF. */ ++#define BIT_CAMERA_CONTROL_OFF (1 << 1) ++#define BIT_CAMERA_CONTROL_ON (1 << 1) ++#define REG_AUDIO_VOLUME 0xF46C /* The register to show volume level */ ++#define FLAG_AUDIO_VOLUME_LEVEL_0 0 ++#define FLAG_AUDIO_VOLUME_LEVEL_1 1 ++#define FLAG_AUDIO_VOLUME_LEVEL_2 2 ++#define FLAG_AUDIO_VOLUME_LEVEL_3 3 ++#define FLAG_AUDIO_VOLUME_LEVEL_4 4 ++#define FLAG_AUDIO_VOLUME_LEVEL_5 5 ++#define FLAG_AUDIO_VOLUME_LEVEL_6 6 ++#define FLAG_AUDIO_VOLUME_LEVEL_7 7 ++#define FLAG_AUDIO_VOLUME_LEVEL_8 8 ++#define FLAG_AUDIO_VOLUME_LEVEL_9 9 ++#define FLAG_AUDIO_VOLUME_LEVEL_10 0x0A ++#define REG_WLAN_STATUS 0xF4FA /* Wlan Status */ ++#define BIT_WLAN_STATUS_ON (1 << 0) ++#define BIT_WLAN_STATUS_OFF (0 << 0) ++#define REG_DISPLAY_LCD 0xF79F /* Black screen Status */ ++#define BIT_DISPLAY_LCD_ON (1 << 0) ++#define BIT_DISPLAY_LCD_OFF (0 << 0) ++#define REG_BACKLIGHT_CTRL 0xF7BD /* LCD backlight control: off/restore */ ++#define BIT_BACKLIGHT_ON (1 << 0) ++#define BIT_BACKLIGHT_OFF (0 << 0) ++ ++/* SCI Event Number from EC */ ++#define SCI_EVENT_NUM_LID 0x23 /* press the lid or not */ ++#define SCI_EVENT_NUM_DISPLAY_TOGGLE 0x24 /* Fn+F3 for display switch */ ++#define SCI_EVENT_NUM_SLEEP 0x25 /* Fn+F1 for entering sleep mode */ ++#define SCI_EVENT_NUM_OVERTEMP 0x26 /* Over-temperature happened */ ++#define SCI_EVENT_NUM_CRT_DETECT 0x27 /* CRT is connected */ ++#define SCI_EVENT_NUM_CAMERA 0x28 /* Camera is on or off */ ++#define SCI_EVENT_NUM_USB_OC2 0x29 /* USB2 Over Current occurred */ ++#define SCI_EVENT_NUM_USB_OC0 0x2A /* USB0 Over Current occurred */ ++#define SCI_EVENT_NUM_AC_BAT 0x2E /* ac & battery relative issue */ ++#define BIT_AC_BAT_BAT_IN 0 ++#define BIT_AC_BAT_AC_IN 1 ++#define BIT_AC_BAT_INIT_CAP 2 ++#define BIT_AC_BAT_CHARGE_MODE 3 ++#define BIT_AC_BAT_STOP_CHARGE 4 ++#define BIT_AC_BAT_BAT_LOW 5 ++#define BIT_AC_BAT_BAT_FULL 6 ++#define SCI_EVENT_NUM_DISPLAY_BRIGHTNESS 0x2D /* LCD backlight brightness adjust */ ++#define SCI_EVENT_NUM_AUDIO_VOLUME 0x2F /* Volume adjust */ ++#define SCI_EVENT_NUM_WLAN 0x30 /* Wlan is on or off */ ++#define SCI_EVENT_NUM_AUDIO_MUTE 0x2C /* Mute is on or off */ ++#define SCI_EVENT_NUM_BLACK_SCREEN 0x2B /* Black screen is on or off */ ++ ++#define SCI_INDEX_LID 0x00 ++#define SCI_INDEX_DISPLAY_TOGGLE 0x01 ++#define SCI_INDEX_SLEEP 0x02 ++#define SCI_INDEX_OVERTEMP 0x03 ++#define SCI_INDEX_CRT_DETECT 0x04 ++#define SCI_INDEX_CAMERA 0x05 ++#define SCI_INDEX_USB_OC2 0x06 ++#define SCI_INDEX_USB_OC0 0x07 ++#define SCI_INDEX_AC_BAT 0x08 ++#define SCI_INDEX_DISPLAY_BRIGHTNESS_INC 0x09 ++#define SCI_INDEX_DISPLAY_BRIGHTNESS_DEC 0x0A ++#define SCI_INDEX_AUDIO_VOLUME_INC 0x0B ++#define SCI_INDEX_AUDIO_VOLUME_DEC 0x0C ++#define SCI_INDEX_WLAN 0x0D ++#define SCI_INDEX_AUDIO_MUTE 0x0E ++#define SCI_INDEX_BLACK_SCREEN 0x0F ++ ++#define SCI_MAX_EVENT_COUNT 0x10 ++ ++/* EC access port for sci communication */ ++#define EC_CMD_PORT 0x66 ++#define EC_STS_PORT 0x66 ++#define EC_DAT_PORT 0x62 ++#define CMD_INIT_IDLE_MODE 0xdd ++#define CMD_EXIT_IDLE_MODE 0xdf ++#define CMD_INIT_RESET_MODE 0xd8 ++#define CMD_REBOOT_SYSTEM 0x8c ++#define CMD_GET_EVENT_NUM 0x84 ++#define CMD_PROGRAM_PIECE 0xda ++ ++/* #define DEBUG_PRINTK */ ++ ++#ifdef DEBUG_PRINTK ++#define PRINTK_DBG(args...) printk(args) ++#else ++#define PRINTK_DBG(args...) ++#endif ++ ++extern void _rdmsr(u32 addr, u32 *hi, u32 *lo); ++extern void _wrmsr(u32 addr, u32 hi, u32 lo); +diff -Nur linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec_misc.c linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec_misc.c +--- linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec_misc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec_misc.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,913 @@ ++/* ++ * EC(Embedded Controller) KB3310B misc device driver on Linux ++ * Author: liujl ++ * Date : 2008-04-20 ++ * ++ * NOTE : ++ * 1, The EC resources accessing and programming are supported. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "ec.h" ++#include "ec_misc.h" + -+ tx_curr = &(titan_ge_eth->tx_desc_area[curr_desc]); -+ tx_curr->buffer_addr = -+ dma_map_single(device, skb->data, skb_headlen(skb), -+ DMA_TO_DEVICE); ++/* open for using rom protection action */ ++#define EC_ROM_PROTECTION ++ ++/* this spinlock is dedicated for ec_read & ec_write function */ ++DEFINE_SPINLOCK(index_access_lock); ++/* this spinlock is dedicated for 62&66 ports access */ ++DEFINE_SPINLOCK(port_access_lock); ++/* information used for programming */ ++struct ec_info ecinfo; ++ ++/* read a byte from EC registers throught index-io */ ++unsigned char ec_read(unsigned short addr) ++{ ++ unsigned char value; ++ unsigned long flags; + -+ titan_ge_eth->tx_skb[curr_desc] = (struct sk_buff *) skb; -+ tx_curr->buffer_len = skb_headlen(skb); ++ spin_lock_irqsave(&index_access_lock, flags); ++ outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH); ++ outb((addr & 0x00ff), EC_IO_PORT_LOW); ++ value = inb(EC_IO_PORT_DATA); ++ spin_unlock_irqrestore(&index_access_lock, flags); + -+ /* Last descriptor enables interrupt and changes ownership */ -+ tx_curr->cmd_sts = 0x1 | (1 << 15) | (1 << 5); ++ return value; ++} ++EXPORT_SYMBOL_GPL(ec_read); + -+ /* Kick the XDMA to start the transfer from memory to the FIFO */ -+ TITAN_GE_WRITE((0x5044 + (port_num << 8)), 0x1); ++/* write a byte to EC registers throught index-io */ ++void ec_write(unsigned short addr, unsigned char val) ++{ ++ unsigned long flags; + -+ /* Current descriptor updated */ -+ titan_ge_eth->tx_curr_desc_q = (curr_desc + 1) % TITAN_GE_TX_QUEUE; ++ spin_lock_irqsave(&index_access_lock, flags); ++ outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH); ++ outb((addr & 0x00ff), EC_IO_PORT_LOW); ++ outb(val, EC_IO_PORT_DATA); ++ inb(EC_IO_PORT_DATA); /* flush the write action */ ++ spin_unlock_irqrestore(&index_access_lock, flags); + -+ /* Prefetch the next descriptor */ -+ prefetch((const void *) -+ &titan_ge_eth->tx_desc_area[titan_ge_eth->tx_curr_desc_q]); ++ return; +} ++EXPORT_SYMBOL_GPL(ec_write); + +/* -+ * Actually does the open of the Ethernet device ++ * ec_query_seq ++ * this function is used for ec command writing and corresponding status query + */ -+static int titan_ge_eth_open(struct net_device *netdev) ++int ec_query_seq(unsigned char cmd) +{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); -+ unsigned int port_num = titan_ge_eth->port_num; -+ struct device *device = &titan_ge_device[port_num]->dev; -+ unsigned long reg_data; -+ unsigned int phy_reg; -+ int err = 0; ++ int timeout; ++ unsigned char status; ++ unsigned long flags; ++ int ret = 0; + -+ /* Stop the Rx activity */ -+ reg_data = TITAN_GE_READ(TITAN_GE_RMAC_CONFIG_1 + (port_num << 12)); -+ reg_data &= ~(0x00000001); -+ TITAN_GE_WRITE((TITAN_GE_RMAC_CONFIG_1 + (port_num << 12)), reg_data); ++ spin_lock_irqsave(&port_access_lock, flags); + -+ /* Clear the port interrupts */ -+ TITAN_GE_WRITE((TITAN_GE_CHANNEL0_INTERRUPT + (port_num << 8)), 0x0); ++ /* make chip goto reset mode */ ++ udelay(EC_REG_DELAY); ++ outb(cmd, EC_CMD_PORT); ++ udelay(EC_REG_DELAY); + -+ if (config_done == 0) { -+ TITAN_GE_WRITE(TITAN_GE_INTR_XDMA_CORE_A, 0); -+ TITAN_GE_WRITE(TITAN_GE_INTR_XDMA_CORE_B, 0); ++ /* check if the command is received by ec */ ++ timeout = EC_CMD_TIMEOUT; ++ status = inb(EC_STS_PORT); ++ while (timeout--) { ++ if (status & (1 << 1)) { ++ status = inb(EC_STS_PORT); ++ udelay(EC_REG_DELAY); ++ continue; ++ } ++ break; + } + -+ /* Set the MAC Address */ -+ memcpy(titan_ge_eth->port_mac_addr, netdev->dev_addr, 6); ++ if (timeout <= 0) { ++ printk(KERN_ERR "EC QUERY SEQ : deadable error : timeout...\n"); ++ ret = -EINVAL; ++ } else { ++ PRINTK_DBG(KERN_INFO ++ "(%x/%d)ec issued command %d status : 0x%x\n", ++ timeout, EC_CMD_TIMEOUT - timeout, cmd, status); ++ } + -+ if (config_done == 0) -+ titan_port_init(netdev, titan_ge_eth); ++ spin_unlock_irqrestore(&port_access_lock, flags); + -+ titan_ge_update_afx(titan_ge_eth); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(ec_query_seq); + -+ /* Allocate the Tx ring now */ -+ titan_ge_eth->tx_ring_skbs = 0; -+ titan_ge_eth->tx_ring_size = TITAN_GE_TX_QUEUE; ++/* enable the chip reset mode */ ++static int ec_init_reset_mode(void) ++{ ++ int timeout; ++ unsigned char status = 0; ++ int ret = 0; + -+ /* Allocate space in the SRAM for the descriptors */ -+ titan_ge_eth->tx_desc_area = (titan_ge_tx_desc *) -+ (titan_ge_sram + TITAN_TX_RING_BYTES * port_num); -+ titan_ge_eth->tx_dma = TITAN_SRAM_BASE + TITAN_TX_RING_BYTES * port_num; ++ /* make chip goto reset mode */ ++ ret = ec_query_seq(CMD_INIT_RESET_MODE); ++ if (ret < 0) { ++ printk(KERN_ERR "ec init reset mode failed.\n"); ++ goto out; ++ } + -+ if (!titan_ge_eth->tx_desc_area) { -+ printk(KERN_ERR -+ "%s: Cannot allocate Tx Ring (size %d bytes) for port %d\n", -+ netdev->name, TITAN_TX_RING_BYTES, port_num); -+ return -ENOMEM; ++ /* make the action take active */ ++ timeout = EC_CMD_TIMEOUT; ++ status = ec_read(REG_POWER_MODE) & FLAG_RESET_MODE; ++ while (timeout--) { ++ if (status) { ++ udelay(EC_REG_DELAY); ++ break; ++ } ++ status = ec_read(REG_POWER_MODE) & FLAG_RESET_MODE; ++ udelay(EC_REG_DELAY); + } ++ if (timeout <= 0) { ++ printk(KERN_ERR "ec rom fixup : can't check reset status.\n"); ++ ret = -EINVAL; ++ } else { ++ PRINTK_DBG(KERN_INFO "(%d/%d)reset 0xf710 : 0x%x\n", timeout, ++ EC_CMD_TIMEOUT - timeout, status); ++ } ++ ++ /* set MCU to reset mode */ ++ udelay(EC_REG_DELAY); ++ status = ec_read(REG_PXCFG); ++ status |= (1 << 0); ++ ec_write(REG_PXCFG, status); ++ udelay(EC_REG_DELAY); ++ ++ /* disable FWH/LPC */ ++ udelay(EC_REG_DELAY); ++ status = ec_read(REG_LPCCFG); ++ status &= ~(1 << 7); ++ ec_write(REG_LPCCFG, status); ++ udelay(EC_REG_DELAY); ++ ++ PRINTK_DBG(KERN_INFO "entering reset mode ok..............\n"); ++ ++ out: ++ return ret; ++} + -+ memset(titan_ge_eth->tx_desc_area, 0, titan_ge_eth->tx_desc_area_size); ++/* make ec exit from reset mode */ ++static void ec_exit_reset_mode(void) ++{ ++ unsigned char regval; + -+ /* Now initialize the Tx descriptor ring */ -+ titan_ge_init_tx_desc_ring(titan_ge_eth, -+ titan_ge_eth->tx_ring_size, -+ (unsigned long) titan_ge_eth->tx_desc_area, -+ (unsigned long) titan_ge_eth->tx_dma); ++ udelay(EC_REG_DELAY); ++ regval = ec_read(REG_LPCCFG); ++ regval |= (1 << 7); ++ ec_write(REG_LPCCFG, regval); ++ regval = ec_read(REG_PXCFG); ++ regval &= ~(1 << 0); ++ ec_write(REG_PXCFG, regval); ++ PRINTK_DBG(KERN_INFO "exit reset mode ok..................\n"); + -+ /* Allocate the Rx ring now */ -+ titan_ge_eth->rx_ring_size = TITAN_GE_RX_QUEUE; -+ titan_ge_eth->rx_ring_skbs = 0; ++ return; ++} + -+ titan_ge_eth->rx_desc_area = -+ (titan_ge_rx_desc *)(titan_ge_sram + 0x1000 + TITAN_RX_RING_BYTES * port_num); ++/* make ec disable WDD */ ++static void ec_disable_WDD(void) ++{ ++ unsigned char status; + -+ titan_ge_eth->rx_dma = TITAN_SRAM_BASE + 0x1000 + TITAN_RX_RING_BYTES * port_num; ++ udelay(EC_REG_DELAY); ++ status = ec_read(REG_WDTCFG); ++ ec_write(REG_WDTPF, 0x03); ++ ec_write(REG_WDTCFG, (status & 0x80) | 0x48); ++ PRINTK_DBG(KERN_INFO "Disable WDD ok..................\n"); + -+ if (!titan_ge_eth->rx_desc_area) { -+ printk(KERN_ERR "%s: Cannot allocate Rx Ring (size %d bytes)\n", -+ netdev->name, TITAN_RX_RING_BYTES); ++ return; ++} + -+ printk(KERN_ERR "%s: Freeing previously allocated TX queues...", -+ netdev->name); ++/* make ec enable WDD */ ++static void ec_enable_WDD(void) ++{ ++ unsigned char status; + -+ dma_free_coherent(device, titan_ge_eth->tx_desc_area_size, -+ (void *) titan_ge_eth->tx_desc_area, -+ titan_ge_eth->tx_dma); ++ udelay(EC_REG_DELAY); ++ status = ec_read(REG_WDTCFG); ++ ec_write(REG_WDT, 0x28); /* set WDT 5sec(0x28) */ ++ ec_write(REG_WDTCFG, (status & 0x80) | 0x03); ++ PRINTK_DBG(KERN_INFO "Enable WDD ok..................\n"); + -+ return -ENOMEM; ++ return; ++} ++ ++/* make ec goto idle mode */ ++static int ec_init_idle_mode(void) ++{ ++ int timeout; ++ unsigned char status = 0; ++ int ret = 0; ++ ++ ec_query_seq(CMD_INIT_IDLE_MODE); ++ ++ /* make the action take active */ ++ timeout = EC_CMD_TIMEOUT; ++ status = ec_read(REG_POWER_MODE) & FLAG_IDLE_MODE; ++ while (timeout--) { ++ if (status) { ++ udelay(EC_REG_DELAY); ++ break; ++ } ++ status = ec_read(REG_POWER_MODE) & FLAG_IDLE_MODE; ++ udelay(EC_REG_DELAY); ++ } ++ if (timeout <= 0) { ++ printk(KERN_ERR "ec rom fixup : can't check out the status.\n"); ++ ret = -EINVAL; ++ } else { ++ PRINTK_DBG(KERN_INFO "(%d/%d)0xf710 : 0x%x\n", timeout, ++ EC_CMD_TIMEOUT - timeout, ec_read(REG_POWER_MODE)); ++ } ++ ++ PRINTK_DBG(KERN_INFO "entering idle mode ok...................\n"); ++ ++ return ret; ++} ++ ++/* make ec exit from idle mode */ ++static int ec_exit_idle_mode(void) ++{ ++ ++ ec_query_seq(CMD_EXIT_IDLE_MODE); ++ ++ PRINTK_DBG(KERN_INFO "exit idle mode ok...................\n"); ++ ++ return 0; ++} ++ ++static int ec_instruction_cycle(void) ++{ ++ unsigned long timeout; ++ int ret = 0; ++ ++ timeout = EC_FLASH_TIMEOUT; ++ while (timeout-- >= 0) { ++ if (!(ec_read(REG_XBISPICFG) & SPICFG_SPI_BUSY)) ++ break; ++ } ++ if (timeout <= 0) { ++ printk(KERN_ERR ++ "EC_INSTRUCTION_CYCLE : timeout for check flag.\n"); ++ ret = -EINVAL; ++ goto out; + } + -+ memset(titan_ge_eth->rx_desc_area, 0, titan_ge_eth->rx_desc_area_size); ++ out: ++ return ret; ++} + -+ /* Now initialize the Rx ring */ -+#ifdef TITAN_GE_JUMBO_FRAMES -+ if ((titan_ge_init_rx_desc_ring -+ (titan_ge_eth, titan_ge_eth->rx_ring_size, TITAN_GE_JUMBO_BUFSIZE, -+ (unsigned long) titan_ge_eth->rx_desc_area, 0, -+ (unsigned long) titan_ge_eth->rx_dma)) == 0) ++/* To see if the ec is in busy state or not. */ ++static inline int ec_flash_busy(unsigned long timeout) ++{ ++ /* assurance the first command be going to rom */ ++ if (ec_instruction_cycle() < 0) ++ return EC_STATE_BUSY; ++#if 1 ++ timeout = timeout / EC_MAX_DELAY_UNIT; ++ while (timeout-- > 0) { ++ /* check the rom's status of busy flag */ ++ ec_write(REG_XBISPICMD, SPICMD_READ_STATUS); ++ if (ec_instruction_cycle() < 0) ++ return EC_STATE_BUSY; ++ if ((ec_read(REG_XBISPIDAT) & 0x01) == 0x00) ++ return EC_STATE_IDLE; ++ udelay(EC_MAX_DELAY_UNIT); ++ } ++ if (timeout <= 0) { ++ printk(KERN_ERR ++ "EC_FLASH_BUSY : timeout for check rom flag.\n"); ++ return EC_STATE_BUSY; ++ } +#else -+ if ((titan_ge_init_rx_desc_ring -+ (titan_ge_eth, titan_ge_eth->rx_ring_size, TITAN_GE_STD_BUFSIZE, -+ (unsigned long) titan_ge_eth->rx_desc_area, 0, -+ (unsigned long) titan_ge_eth->rx_dma)) == 0) ++ /* check the rom's status of busy flag */ ++ ec_write(REG_XBISPICMD, SPICMD_READ_STATUS); ++ if (ec_instruction_cycle() < 0) ++ return EC_STATE_BUSY; ++ ++ timeout = timeout / EC_MAX_DELAY_UNIT; ++ while (timeout-- > 0) { ++ if ((ec_read(REG_XBISPIDAT) & 0x01) == 0x00) ++ return EC_STATE_IDLE; ++ udelay(EC_MAX_DELAY_UNIT); ++ } ++ if (timeout <= 0) { ++ printk(KERN_ERR ++ "EC_FLASH_BUSY : timeout for check rom flag.\n"); ++ return EC_STATE_BUSY; ++ } +#endif -+ panic("%s: Error initializing RX Ring\n", netdev->name); + -+ /* Fill the Rx ring with the SKBs */ -+ titan_ge_port_start(netdev, titan_ge_eth); ++ return EC_STATE_IDLE; ++} + -+ /* -+ * Check if Interrupt Coalscing needs to be turned on. The -+ * values specified in the register is multiplied by -+ * (8 x 64 nanoseconds) to determine when an interrupt should -+ * be sent to the CPU. -+ */ ++static int rom_instruction_cycle(unsigned char cmd) ++{ ++ unsigned long timeout = 0; ++ ++ switch (cmd) { ++ case SPICMD_READ_STATUS: ++ case SPICMD_WRITE_ENABLE: ++ case SPICMD_WRITE_DISABLE: ++ case SPICMD_READ_BYTE: ++ case SPICMD_HIGH_SPEED_READ: ++ timeout = 0; ++ break; ++ case SPICMD_WRITE_STATUS: ++ timeout = 300 * 1000; ++ break; ++ case SPICMD_BYTE_PROGRAM: ++ timeout = 5 * 1000; ++ break; ++ case SPICMD_SST_SEC_ERASE: ++ case SPICMD_SEC_ERASE: ++ timeout = 1000 * 1000; ++ break; ++ case SPICMD_SST_BLK_ERASE: ++ case SPICMD_BLK_ERASE: ++ timeout = 3 * 1000 * 1000; ++ break; ++ case SPICMD_SST_CHIP_ERASE: ++ case SPICMD_CHIP_ERASE: ++ timeout = 20 * 1000 * 1000; ++ break; ++ default: ++ timeout = EC_SPICMD_STANDARD_TIMEOUT; ++ } ++ if (timeout == 0) ++ return ec_instruction_cycle(); ++ if (timeout < EC_SPICMD_STANDARD_TIMEOUT) ++ timeout = EC_SPICMD_STANDARD_TIMEOUT; ++ ++ return ec_flash_busy(timeout); ++} ++ ++/* delay for start/stop action */ ++static void delay_spi(int n) ++{ ++ while (n--) ++ inb(EC_IO_PORT_HIGH); ++} ++ ++/* start the action to spi rom function */ ++static void ec_start_spi(void) ++{ ++ unsigned char val; ++ ++ delay_spi(SPI_FINISH_WAIT_TIME); ++ val = ec_read(REG_XBISPICFG) | SPICFG_EN_SPICMD | SPICFG_AUTO_CHECK; ++ ec_write(REG_XBISPICFG, val); ++ delay_spi(SPI_FINISH_WAIT_TIME); ++} ++ ++/* stop the action to spi rom function */ ++static void ec_stop_spi(void) ++{ ++ unsigned char val; ++ ++ delay_spi(SPI_FINISH_WAIT_TIME); ++ val = ++ ec_read(REG_XBISPICFG) & (~(SPICFG_EN_SPICMD | SPICFG_AUTO_CHECK)); ++ ec_write(REG_XBISPICFG, val); ++ delay_spi(SPI_FINISH_WAIT_TIME); ++} ++ ++/* read one byte from xbi interface */ ++static int ec_read_byte(unsigned int addr, unsigned char *byte) ++{ ++ int ret = 0; + -+ if (TITAN_GE_TX_COAL) { -+ titan_ge_eth->tx_int_coal = -+ titan_ge_tx_coal(TITAN_GE_TX_COAL, port_num); ++ /* enable spicmd writing. */ ++ ec_start_spi(); ++ ++ /* enable write spi flash */ ++ ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE); ++ if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) { ++ printk(KERN_ERR "EC_READ_BYTE : SPICMD_WRITE_ENABLE failed.\n"); ++ ret = -EINVAL; ++ goto out; + } + -+ err = titan_ge_mdio_read(port_num, TITAN_GE_MDIO_PHY_STATUS, &phy_reg); -+ if (err == TITAN_GE_MDIO_ERROR) { ++ /* write the address */ ++ ec_write(REG_XBISPIA2, (addr & 0xff0000) >> 16); ++ ec_write(REG_XBISPIA1, (addr & 0x00ff00) >> 8); ++ ec_write(REG_XBISPIA0, (addr & 0x0000ff) >> 0); ++ /* start action */ ++ ec_write(REG_XBISPICMD, SPICMD_HIGH_SPEED_READ); ++ if (rom_instruction_cycle(SPICMD_HIGH_SPEED_READ) == EC_STATE_BUSY) { + printk(KERN_ERR -+ "Could not read PHY control register 0x11 \n"); -+ return TITAN_ERROR; ++ "EC_READ_BYTE : SPICMD_HIGH_SPEED_READ failed.\n"); ++ ret = -EINVAL; ++ goto out; + } -+ if (!(phy_reg & 0x0400)) { -+ netif_carrier_off(netdev); -+ netif_stop_queue(netdev); -+ return TITAN_ERROR; -+ } else { -+ netif_carrier_on(netdev); -+ netif_start_queue(netdev); ++ ++ *byte = ec_read(REG_XBISPIDAT); ++ ++ out: ++ /* disable spicmd writing. */ ++ ec_stop_spi(); ++ ++ return ret; ++} ++ ++/* write one byte to ec rom */ ++static int ec_write_byte(unsigned int addr, unsigned char byte) ++{ ++ int ret = 0; ++ ++ /* enable spicmd writing. */ ++ ec_start_spi(); ++ ++ /* enable write spi flash */ ++ ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE); ++ if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) { ++ printk(KERN_ERR ++ "EC_WRITE_BYTE : SPICMD_WRITE_ENABLE failed.\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* write the address */ ++ ec_write(REG_XBISPIA2, (addr & 0xff0000) >> 16); ++ ec_write(REG_XBISPIA1, (addr & 0x00ff00) >> 8); ++ ec_write(REG_XBISPIA0, (addr & 0x0000ff) >> 0); ++ ec_write(REG_XBISPIDAT, byte); ++ /* start action */ ++ ec_write(REG_XBISPICMD, SPICMD_BYTE_PROGRAM); ++ if (rom_instruction_cycle(SPICMD_BYTE_PROGRAM) == EC_STATE_BUSY) { ++ printk(KERN_ERR ++ "EC_WRITE_BYTE : SPICMD_BYTE_PROGRAM failed.\n"); ++ ret = -EINVAL; ++ goto out; + } + -+ return TITAN_OK; ++ out: ++ /* disable spicmd writing. */ ++ ec_stop_spi(); ++ ++ return ret; +} + -+/* -+ * Queue the packet for Tx. Currently no support for zero copy, -+ * checksum offload and Scatter Gather. The chip does support -+ * Scatter Gather only. But, that wont help here since zero copy -+ * requires support for Tx checksumming also. -+ */ -+int titan_ge_start_xmit(struct sk_buff *skb, struct net_device *netdev) ++/* unprotect SPI ROM */ ++/* EC_ROM_unprotect function code */ ++static int EC_ROM_unprotect(void) +{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); -+ unsigned long flags; -+ struct net_device_stats *stats; -+//printk("titan_ge_start_xmit\n"); ++ unsigned char status; ++ ++ /* enable write spi flash */ ++ ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE); ++ if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) { ++ printk(KERN_ERR ++ "EC_UNIT_ERASE : SPICMD_WRITE_ENABLE failed.\n"); ++ return 1; ++ } ++ ++ /* unprotect the status register of rom */ ++ ec_write(REG_XBISPICMD, SPICMD_READ_STATUS); ++ if (rom_instruction_cycle(SPICMD_READ_STATUS) == EC_STATE_BUSY) { ++ printk(KERN_ERR "EC_UNIT_ERASE : SPICMD_READ_STATUS failed.\n"); ++ return 1; ++ } ++ status = ec_read(REG_XBISPIDAT); ++ ec_write(REG_XBISPIDAT, status & 0x02); ++ if (ec_instruction_cycle() < 0) { ++ printk(KERN_ERR "EC_UNIT_ERASE : write status value failed.\n"); ++ return 1; ++ } ++ ++ ec_write(REG_XBISPICMD, SPICMD_WRITE_STATUS); ++ if (rom_instruction_cycle(SPICMD_WRITE_STATUS) == EC_STATE_BUSY) { ++ printk(KERN_ERR ++ "EC_UNIT_ERASE : SPICMD_WRITE_STATUS failed.\n"); ++ return 1; ++ } ++ ++ /* enable write spi flash */ ++ ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE); ++ if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) { ++ printk(KERN_ERR ++ "EC_UNIT_ERASE : SPICMD_WRITE_ENABLE failed.\n"); ++ return 1; ++ } ++ ++ return 0; ++} + -+ stats = &titan_ge_eth->stats; -+ spin_lock_irqsave(&titan_ge_eth->lock, flags); ++/* erase one block or chip or sector as needed */ ++static int ec_unit_erase(unsigned char erase_cmd, unsigned int addr) ++{ ++ unsigned char status; ++ int ret = 0, i = 0; ++ int unprotect_count = 3; ++ int check_flag = 0; ++ ++ /* enable spicmd writing. */ ++ ec_start_spi(); ++ ++#ifdef EC_ROM_PROTECTION ++ /* added for re-check SPICMD_READ_STATUS */ ++ while (unprotect_count-- > 0) { ++ if (EC_ROM_unprotect()) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* first time:500ms --> 5.5sec -->10.5sec */ ++ for (i = 0; i < ((2 - unprotect_count) * 100 + 10); i++) ++ udelay(50000); ++ ec_write(REG_XBISPICMD, SPICMD_READ_STATUS); ++ if (rom_instruction_cycle(SPICMD_READ_STATUS) ++ == EC_STATE_BUSY) { ++ printk(KERN_ERR ++ "EC_PROGRAM_ROM : SPICMD_READ_STATUS failed.\n"); ++ } else { ++ status = ec_read(REG_XBISPIDAT); ++ PRINTK_DBG(KERN_INFO "Read unprotect status : 0x%x\n", ++ status); ++ if ((status & 0x1C) == 0x00) { ++ PRINTK_DBG(KERN_INFO ++ "Read unprotect status OK1 : 0x%x\n", ++ status & 0x1C); ++ check_flag = 1; ++ break; ++ } ++ } ++ } + -+ if ((TITAN_GE_TX_QUEUE - titan_ge_eth->tx_ring_skbs) <= -+ (skb_shinfo(skb)->nr_frags + 1)) { -+ netif_stop_queue(netdev); -+ spin_unlock_irqrestore(&titan_ge_eth->lock, flags); -+ printk(KERN_ERR "Tx OOD \n"); ++ if (!check_flag) { ++ printk(KERN_INFO "SPI ROM unprotect fail.\n"); + return 1; + } ++#endif ++ ++ /* block address fill */ ++ if (erase_cmd == SPICMD_BLK_ERASE) { ++ ec_write(REG_XBISPIA2, (addr & 0x00ff0000) >> 16); ++ ec_write(REG_XBISPIA1, (addr & 0x0000ff00) >> 8); ++ ec_write(REG_XBISPIA0, (addr & 0x000000ff) >> 0); ++ } ++ ++ /* erase the whole chip first */ ++ ec_write(REG_XBISPICMD, erase_cmd); ++ if (rom_instruction_cycle(erase_cmd) == EC_STATE_BUSY) { ++ printk(KERN_ERR "EC_UNIT_ERASE : erase failed.\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ out: ++ /* disable spicmd writing. */ ++ ec_stop_spi(); ++ ++ return ret; ++} ++ ++/* update the whole rom content with H/W mode ++ * PLEASE USING ec_unit_erase() FIRSTLY ++ */ ++static int ec_program_rom(struct ec_info *info, int flag) ++{ ++ unsigned int addr = 0; ++ unsigned long size = 0; ++ unsigned char *ptr = NULL; ++ unsigned char data; ++ unsigned char val = 0; ++ int ret = 0; ++ int i, j; ++ unsigned char status; ++ ++ /* modify for program serial No. ++ * set IE_START_ADDR & use idle mode, ++ * disable WDD ++ */ ++ if (flag == PROGRAM_FLAG_ROM) { ++ ret = ec_init_reset_mode(); ++ addr = info->start_addr + EC_START_ADDR; ++ PRINTK_DBG(KERN_INFO "PROGRAM_FLAG_ROM..............\n"); ++ } else if (flag == PROGRAM_FLAG_IE) { ++ ret = ec_init_idle_mode(); ++ ec_disable_WDD(); ++ addr = info->start_addr + IE_START_ADDR; ++ PRINTK_DBG(KERN_INFO "PROGRAM_FLAG_IE..............\n"); ++ } else { ++ return 0; ++ } + -+ titan_ge_tx_queue(titan_ge_eth, skb); -+ titan_ge_eth->tx_ring_skbs++; ++ if (ret < 0) { ++ if (flag == PROGRAM_FLAG_IE) ++ ec_enable_WDD(); ++ return ret; ++ } ++ ++ size = info->size; ++ ptr = info->buf; ++ PRINTK_DBG(KERN_INFO "starting update ec ROM..............\n"); ++ ++ ret = ec_unit_erase(SPICMD_BLK_ERASE, addr); ++ if (ret) { ++ printk(KERN_ERR "program ec : erase block failed.\n"); ++ goto out; ++ } ++ PRINTK_DBG(KERN_ERR "program ec : erase block OK.\n"); ++ ++ i = 0; ++ while (i < size) { ++ data = *(ptr + i); ++ ec_write_byte(addr, data); ++ ec_read_byte(addr, &val); ++ if (val != data) { ++ ec_write_byte(addr, data); ++ ec_read_byte(addr, &val); ++ if (val != data) { ++ printk(KERN_INFO ++ "EC : Second flash program failed at:\t"); ++ printk(KERN_INFO ++ "addr : 0x%x, source : 0x%x, dest: 0x%x\n", ++ addr, data, val); ++ printk(KERN_INFO "This should not happen... STOP\n"); ++ break; ++ } ++ } ++ i++; ++ addr++; ++ } ++ ++#ifdef EC_ROM_PROTECTION ++ /* we should start spi access firstly */ ++ ec_start_spi(); ++ ++ /* enable write spi flash */ ++ ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE); ++ if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) { ++ printk(KERN_ERR ++ "EC_PROGRAM_ROM : SPICMD_WRITE_ENABLE failed.\n"); ++ goto out1; ++ } ++ ++ /* protect the status register of rom */ ++ ec_write(REG_XBISPICMD, SPICMD_READ_STATUS); ++ if (rom_instruction_cycle(SPICMD_READ_STATUS) == EC_STATE_BUSY) { ++ printk(KERN_ERR ++ "EC_PROGRAM_ROM : SPICMD_READ_STATUS failed.\n"); ++ goto out1; ++ } ++ status = ec_read(REG_XBISPIDAT); + -+ if (TITAN_GE_TX_QUEUE <= (titan_ge_eth->tx_ring_skbs + 4)) { -+ spin_unlock_irqrestore(&titan_ge_eth->lock, flags); -+ titan_ge_free_tx_queue(titan_ge_eth); -+ spin_lock_irqsave(&titan_ge_eth->lock, flags); ++ ec_write(REG_XBISPIDAT, status | 0x1C); ++ if (ec_instruction_cycle() < 0) { ++ printk(KERN_ERR ++ "EC_PROGRAM_ROM : write status value failed.\n"); ++ goto out1; ++ } ++ ++ ec_write(REG_XBISPICMD, SPICMD_WRITE_STATUS); ++ if (rom_instruction_cycle(SPICMD_WRITE_STATUS) == EC_STATE_BUSY) { ++ printk(KERN_ERR ++ "EC_PROGRAM_ROM : SPICMD_WRITE_STATUS failed.\n"); ++ goto out1; ++ } ++#endif ++ ++ /* disable the write action to spi rom */ ++ ec_write(REG_XBISPICMD, SPICMD_WRITE_DISABLE); ++ if (rom_instruction_cycle(SPICMD_WRITE_DISABLE) == EC_STATE_BUSY) { ++ printk(KERN_ERR ++ "EC_PROGRAM_ROM : SPICMD_WRITE_DISABLE failed.\n"); ++ goto out1; + } + -+ stats->tx_bytes += skb->len; -+ stats->tx_packets++; ++ out1: ++ /* we should stop spi access firstly */ ++ ec_stop_spi(); ++ out: ++ /* for security */ ++ for (j = 0; j < 2000; j++) ++ udelay(1000); ++ ++ /* modify for program serial No. ++ * after program No exit idle mode ++ * and enable WDD ++ */ ++ if (flag == PROGRAM_FLAG_ROM) { ++ /* exit from the reset mode */ ++ ec_exit_reset_mode(); ++ } else { ++ /* ec exit from idle mode */ ++ ret = ec_exit_idle_mode(); ++ ec_enable_WDD(); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/* ioctl */ ++static int misc_ioctl(struct inode *inode, struct file *filp, u_int cmd, ++ u_long arg) ++{ ++ void __user *ptr = (void __user *)arg; ++ struct ec_reg *ecreg = (struct ec_reg *)(filp->private_data); ++ int ret = 0; ++ ++ switch (cmd) { ++ case IOCTL_RDREG: ++ ret = copy_from_user(ecreg, ptr, sizeof(struct ec_reg)); ++ if (ret) { ++ printk(KERN_ERR "reg read : copy from user error.\n"); ++ return -EFAULT; ++ } ++ if ((ecreg->addr > EC_MAX_REGADDR) ++ || (ecreg->addr < EC_MIN_REGADDR)) { ++ printk(KERN_ERR ++ "reg read : out of register address range.\n"); ++ return -EINVAL; ++ } ++ ecreg->val = ec_read(ecreg->addr); ++ ret = copy_to_user(ptr, ecreg, sizeof(struct ec_reg)); ++ if (ret) { ++ printk(KERN_ERR "reg read : copy to user error.\n"); ++ return -EFAULT; ++ } ++ break; ++ case IOCTL_WRREG: ++ ret = copy_from_user(ecreg, ptr, sizeof(struct ec_reg)); ++ if (ret) { ++ printk(KERN_ERR "reg write : copy from user error.\n"); ++ return -EFAULT; ++ } ++ if ((ecreg->addr > EC_MAX_REGADDR) ++ || (ecreg->addr < EC_MIN_REGADDR)) { ++ printk(KERN_ERR ++ "reg write : out of register address range.\n"); ++ return -EINVAL; ++ } ++ ec_write(ecreg->addr, ecreg->val); ++ break; ++ case IOCTL_READ_EC: ++ ret = copy_from_user(ecreg, ptr, sizeof(struct ec_reg)); ++ if (ret) { ++ printk(KERN_ERR "spi read : copy from user error.\n"); ++ return -EFAULT; ++ } ++ if ((ecreg->addr > EC_RAM_ADDR) ++ && (ecreg->addr < EC_MAX_REGADDR)) { ++ printk(KERN_ERR ++ "spi read : out of register address range.\n"); ++ return -EINVAL; ++ } ++ ec_read_byte(ecreg->addr, &(ecreg->val)); ++ ret = copy_to_user(ptr, ecreg, sizeof(struct ec_reg)); ++ if (ret) { ++ printk(KERN_ERR "spi read : copy to user error.\n"); ++ return -EFAULT; ++ } ++ break; ++ case IOCTL_PROGRAM_IE: ++ ecinfo.start_addr = EC_START_ADDR; ++ ecinfo.size = EC_CONTENT_MAX_SIZE; ++ ecinfo.buf = (u8 *) kmalloc(ecinfo.size, GFP_KERNEL); ++ if (ecinfo.buf == NULL) { ++ printk(KERN_ERR "program ie : kmalloc failed.\n"); ++ return -ENOMEM; ++ } ++ ret = copy_from_user(ecinfo.buf, (u8 *) ptr, ecinfo.size); ++ if (ret) { ++ printk(KERN_ERR "program ie : copy from user error.\n"); ++ kfree(ecinfo.buf); ++ ecinfo.buf = NULL; ++ return -EFAULT; ++ } ++ ++ /* use ec_program_rom to write serial No */ ++ ec_program_rom(&ecinfo, PROGRAM_FLAG_IE); ++ ++ kfree(ecinfo.buf); ++ ecinfo.buf = NULL; ++ break; ++ case IOCTL_PROGRAM_EC: ++ ecinfo.start_addr = EC_START_ADDR; ++ if (get_user((ecinfo.size), (u32 *) ptr)) { ++ printk(KERN_ERR "program ec : get user error.\n"); ++ return -EFAULT; ++ } ++ if ((ecinfo.size) > EC_CONTENT_MAX_SIZE) { ++ printk(KERN_ERR "program ec : size out of limited.\n"); ++ return -EINVAL; ++ } ++ ecinfo.buf = (u8 *) kmalloc(ecinfo.size, GFP_KERNEL); ++ if (ecinfo.buf == NULL) { ++ printk(KERN_ERR "program ec : kmalloc failed.\n"); ++ return -ENOMEM; ++ } ++ ret = copy_from_user(ecinfo.buf, ((u8 *) ptr + 4), ecinfo.size); ++ if (ret) { ++ printk(KERN_ERR "program ec : copy from user error.\n"); ++ kfree(ecinfo.buf); ++ ecinfo.buf = NULL; ++ return -EFAULT; ++ } ++ ++ ec_program_rom(&ecinfo, PROGRAM_FLAG_ROM); + -+ spin_unlock_irqrestore(&titan_ge_eth->lock, flags); ++ kfree(ecinfo.buf); ++ ecinfo.buf = NULL; ++ break; + -+ netdev->trans_start = jiffies; ++ default: ++ break; ++ } + + return 0; +} + -+/* -+ * Actually does the Rx. Rx side checksumming supported. -+ */ -+static int titan_ge_rx(struct net_device *netdev, int port_num, -+ titan_ge_port_info * titan_ge_port, -+ titan_ge_packet * packet) ++static long misc_compat_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ return misc_ioctl(file->f_dentry->d_inode, file, cmd, arg); ++} ++ ++static int misc_open(struct inode *inode, struct file *filp) +{ -+ int rx_curr_desc, rx_used_desc; -+ volatile titan_ge_rx_desc *rx_desc; ++ struct ec_reg *ecreg = NULL; ++ ecreg = kmalloc(sizeof(struct ec_reg), GFP_KERNEL); ++ if (ecreg) ++ filp->private_data = ecreg; + -+ rx_curr_desc = titan_ge_port->rx_curr_desc_q; -+ rx_used_desc = titan_ge_port->rx_used_desc_q; ++ return ecreg ? 0 : -ENOMEM; ++} + -+ if (((rx_curr_desc + 1) % TITAN_GE_RX_QUEUE) == rx_used_desc) -+ return TITAN_ERROR; ++static int misc_release(struct inode *inode, struct file *filp) ++{ ++ struct ec_reg *ecreg = (struct ec_reg *)(filp->private_data); + -+ rx_desc = &(titan_ge_port->rx_desc_area[rx_curr_desc]); ++ filp->private_data = NULL; ++ kfree(ecreg); + -+ if (rx_desc->cmd_sts & TITAN_GE_RX_BUFFER_OWNED) -+ return TITAN_ERROR; ++ return 0; ++} + -+ packet->skb = titan_ge_port->rx_skb[rx_curr_desc]; -+ packet->len = (rx_desc->cmd_sts & 0x7fff); ++static const struct file_operations ecmisc_fops = { ++ .open = misc_open, ++ .release = misc_release, ++ .read = NULL, ++ .write = NULL, ++#ifdef CONFIG_64BIT ++ .compat_ioctl = misc_compat_ioctl, ++#else ++ .ioctl = misc_ioctl, ++#endif ++}; + -+ /* -+ * At this point, we dont know if the checksumming -+ * actually helps relieve CPU. So, keep it for -+ * port 0 only -+ */ -+ packet->checksum = ntohs((rx_desc->buffer & 0xffff0000) >> 16); -+ packet->cmd_sts = rx_desc->cmd_sts; ++static struct miscdevice ecmisc_device = { ++ .minor = ECMISC_MINOR_DEV, ++ .name = EC_MISC_DEV, ++ .fops = &ecmisc_fops ++}; + -+ titan_ge_port->rx_curr_desc_q = (rx_curr_desc + 1) % TITAN_GE_RX_QUEUE; ++static int __init ecmisc_init(void) ++{ ++ int ret; + -+ /* Prefetch the next descriptor */ -+ prefetch((const void *) -+ &titan_ge_port->rx_desc_area[titan_ge_port->rx_curr_desc_q + 1]); ++ printk(KERN_INFO "EC misc device init.\n"); ++ ret = misc_register(&ecmisc_device); + -+ return TITAN_OK; ++ return ret; +} + -+/* -+ * Free the Tx queue of the used SKBs -+ */ -+static int titan_ge_free_tx_queue(titan_ge_port_info *titan_ge_eth) ++static void __exit ecmisc_exit(void) +{ -+ unsigned long flags; -+ -+ /* Take the lock */ -+ spin_lock_irqsave(&(titan_ge_eth->lock), flags); -+ -+ while (titan_ge_return_tx_desc(titan_ge_eth, titan_ge_eth->port_num) == 0) -+ if (titan_ge_eth->tx_ring_skbs != 1) -+ titan_ge_eth->tx_ring_skbs--; ++ printk(KERN_INFO "EC misc device exit.\n"); ++ misc_deregister(&ecmisc_device); ++} + -+ spin_unlock_irqrestore(&titan_ge_eth->lock, flags); ++module_init(ecmisc_init); ++module_exit(ecmisc_exit); + -+ return TITAN_OK; -+} ++MODULE_AUTHOR("liujl "); ++MODULE_DESCRIPTION("KB3310 resources misc Management"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec_misc_fn.h linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec_misc_fn.h +--- linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec_misc_fn.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec_misc_fn.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,16 @@ + +/* -+ * Threshold beyond which we do the cleaning of -+ * Tx queue and new allocation for the Rx -+ * queue ++ * EC(Embedded Controller) KB3310B misc device export functions header file ++ * ++ * Author: liujl ++ * Date : 2009-03-16 ++ * ++ * EC relative export header file. + */ -+#define TX_THRESHOLD 4 -+#define RX_THRESHOLD 10 + ++/* the general ec index-io port read action */ ++extern unsigned char ec_read(unsigned short addr); ++/* the general ec index-io port write action */ ++extern void ec_write(unsigned short addr, unsigned char val); ++/* query sequence of 62/66 port access routine */ ++extern int ec_query_seq(unsigned char cmd); +diff -Nur linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec_misc.h linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec_misc.h +--- linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec_misc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec_misc.h 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,191 @@ +/* -+ * Receive the packets and send it to the kernel. ++ * EC(Embedded Controller) KB3310B Misc device driver header file in linux ++ * Author : liujl ++ * Date : 2008-04-20 ++ * ++ * NOTE : ++ * 1, The application layer for reading, writing ec registers and code ++ * program are supported. + */ -+static int titan_ge_receive_queue(struct net_device *netdev, unsigned int max) -+{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); -+ unsigned int port_num = titan_ge_eth->port_num; -+ titan_ge_packet packet; -+ struct net_device_stats *stats; -+ struct sk_buff *skb; -+ unsigned long received_packets = 0; -+ unsigned int ack; -+ -+ stats = &titan_ge_eth->stats; + -+ while ((--max) -+ && (titan_ge_rx(netdev, port_num, titan_ge_eth, &packet) == TITAN_OK)) { -+ skb = (struct sk_buff *) packet.skb; ++/* ec delay time 500us for register and status access */ ++#define EC_REG_DELAY 500 /* unit : us */ ++ ++/* version burned address */ ++#define VER_ADDR 0xf7a1 ++#define VER_MAX_SIZE 7 ++#define EC_ROM_MAX_SIZE 0x10000 ++ ++/* ec internal register */ ++#define REG_POWER_MODE 0xF710 ++#define FLAG_NORMAL_MODE 0x00 ++#define FLAG_IDLE_MODE 0x01 ++#define FLAG_RESET_MODE 0x02 ++ ++/* ec update program flag */ ++#define PROGRAM_FLAG_NONE 0x00 ++#define PROGRAM_FLAG_IE 0x01 ++#define PROGRAM_FLAG_ROM 0x02 ++ ++/* XBI relative registers */ ++#define REG_XBISEG0 0xFEA0 ++#define REG_XBISEG1 0xFEA1 ++#define REG_XBIRSV2 0xFEA2 ++#define REG_XBIRSV3 0xFEA3 ++#define REG_XBIRSV4 0xFEA4 ++#define REG_XBICFG 0xFEA5 ++#define REG_XBICS 0xFEA6 ++#define REG_XBIWE 0xFEA7 ++#define REG_XBISPIA0 0xFEA8 ++#define REG_XBISPIA1 0xFEA9 ++#define REG_XBISPIA2 0xFEAA ++#define REG_XBISPIDAT 0xFEAB ++#define REG_XBISPICMD 0xFEAC ++#define REG_XBISPICFG 0xFEAD ++#define REG_XBISPIDATR 0xFEAE ++#define REG_XBISPICFG2 0xFEAF ++ ++/* commands definition for REG_XBISPICMD */ ++#define SPICMD_WRITE_STATUS 0x01 ++#define SPICMD_BYTE_PROGRAM 0x02 ++#define SPICMD_READ_BYTE 0x03 ++#define SPICMD_WRITE_DISABLE 0x04 ++#define SPICMD_READ_STATUS 0x05 ++#define SPICMD_WRITE_ENABLE 0x06 ++#define SPICMD_HIGH_SPEED_READ 0x0B ++#define SPICMD_POWER_DOWN 0xB9 ++#define SPICMD_SST_EWSR 0x50 ++#define SPICMD_SST_SEC_ERASE 0x20 ++#define SPICMD_SST_BLK_ERASE 0x52 ++#define SPICMD_SST_CHIP_ERASE 0x60 ++#define SPICMD_FRDO 0x3B ++#define SPICMD_SEC_ERASE 0xD7 ++#define SPICMD_BLK_ERASE 0xD8 ++#define SPICMD_CHIP_ERASE 0xC7 ++ ++/* bits definition for REG_XBISPICFG */ ++#define SPICFG_AUTO_CHECK 0x01 ++#define SPICFG_SPI_BUSY 0x02 ++#define SPICFG_DUMMY_READ 0x04 ++#define SPICFG_EN_SPICMD 0x08 ++#define SPICFG_LOW_SPICS 0x10 ++#define SPICFG_EN_SHORT_READ 0x20 ++#define SPICFG_EN_OFFSET_READ 0x40 ++#define SPICFG_EN_FAST_READ 0x80 ++ ++/* SMBUS relative register block according to the EC datasheet. */ ++#define REG_SMBTCRC 0xff92 ++#define REG_SMBPIN 0xff93 ++#define REG_SMBCFG 0xff94 ++#define REG_SMBEN 0xff95 ++#define REG_SMBPF 0xff96 ++#define REG_SMBRCRC 0xff97 ++#define REG_SMBPRTCL 0xff98 ++#define REG_SMBSTS 0xff99 ++#define REG_SMBADR 0xff9a ++#define REG_SMBCMD 0xff9b ++#define REG_SMBDAT_START 0xff9c ++#define REG_SMBDAT_END 0xffa3 ++#define SMBDAT_SIZE 8 ++#define REG_SMBRSA 0xffa4 ++#define REG_SMBCNT 0xffbc ++#define REG_SMBAADR 0xffbd ++#define REG_SMBADAT0 0xffbe ++#define REG_SMBADAT1 0xffbf ++ ++/* watchdog timer registers */ ++#define REG_WDTCFG 0xfe80 ++#define REG_WDTPF 0xfe81 ++#define REG_WDT 0xfe82 ++ ++/* lpc configure register */ ++#define REG_LPCCFG 0xfe95 ++ ++/* 8051 reg */ ++#define REG_PXCFG 0xff14 ++ ++/* Fan register in KB3310 */ ++#define REG_ECFAN_SPEED_LEVEL 0xf4e4 ++#define REG_ECFAN_SWITCH 0xf4d2 ++ ++/* the ec flash rom id number */ ++#define EC_ROM_PRODUCT_ID_SPANSION 0x01 ++#define EC_ROM_PRODUCT_ID_MXIC 0xC2 ++#define EC_ROM_PRODUCT_ID_AMIC 0x37 ++#define EC_ROM_PRODUCT_ID_EONIC 0x1C ++ ++/* Ec misc device name */ ++#define EC_MISC_DEV "ec_misc" ++ ++/* Ec misc device minor number */ ++#define ECMISC_MINOR_DEV MISC_DYNAMIC_MINOR ++ ++#define EC_IOC_MAGIC 'E' ++/* misc ioctl operations */ ++#define IOCTL_RDREG _IOR(EC_IOC_MAGIC, 1, int) ++#define IOCTL_WRREG _IOW(EC_IOC_MAGIC, 2, int) ++#define IOCTL_READ_EC _IOR(EC_IOC_MAGIC, 3, int) ++#define IOCTL_PROGRAM_IE _IOW(EC_IOC_MAGIC, 4, int) ++#define IOCTL_PROGRAM_EC _IOW(EC_IOC_MAGIC, 5, int) ++ ++/* start address for programming of EC content or IE */ ++/* ec running code start address */ ++#define EC_START_ADDR 0x00000000 ++/* ec information element storing address */ ++#define IE_START_ADDR 0x00020000 ++ ++/* EC state */ ++#define EC_STATE_IDLE 0x00 /* ec in idle state */ ++#define EC_STATE_BUSY 0x01 /* ec in busy state */ ++ ++/* timeout value for programming */ ++#define EC_FLASH_TIMEOUT 0x1000 /* ec program timeout */ ++/* command checkout timeout including cmd to port or state flag check */ ++#define EC_CMD_TIMEOUT 0x1000 ++#define EC_SPICMD_STANDARD_TIMEOUT (4 * 1000) /* unit : us */ ++#define EC_MAX_DELAY_UNIT (10) /* every time for polling */ ++#define SPI_FINISH_WAIT_TIME 10 ++/* EC content max size */ ++#define EC_CONTENT_MAX_SIZE (64 * 1024) ++#define IE_CONTENT_MAX_SIZE (0x100000 - IE_START_ADDR) + -+ titan_ge_eth->rx_ring_skbs--; -+ -+ if (--titan_ge_eth->rx_work_limit < 0) -+ break; -+ received_packets++; ++/* ++ * piece structure : ++ * ------------------------------ ++ * | 1byte | 3 bytes | 28 bytes | ++ * | flag | addr | data | ++ * ------------------------------ ++ * flag : ++ * bit0 : '1' for first piece, '0' for other ++ * addr : ++ * address for EC to burn the data to(rom address) ++ * data : ++ * data which we should burn to the ec rom ++ * ++ * NOTE: ++ * so far max size should be 256B, or we should change the address-1 value. ++ * piece is used for IE program ++ */ ++#define PIECE_SIZE (32 - 1 - 3) ++#define FIRST_PIECE_YES 1 ++#define FIRST_PIECE_NO 0 ++/* piece program status reg from ec firmware */ ++#define PIECE_STATUS_REG 0xF77C ++/* piece program status reg done flag */ ++#define PIECE_STATUS_PROGRAM_DONE 0x80 ++/* piece program status reg error flag */ ++#define PIECE_STATUS_PROGRAM_ERROR 0x40 ++/* 32bytes should be stored here */ ++#define PIECE_START_ADDR 0xF800 ++ ++/* the register operation access struct */ ++struct ec_reg { ++ u32 addr; /* the address of kb3310 registers */ ++ u8 val; /* the register value */ ++}; + -+ stats->rx_packets++; -+ stats->rx_bytes += packet.len; ++struct ec_info { ++ u32 start_addr; ++ u32 size; ++ u8 *buf; ++}; +diff -Nur linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec_sci.c linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec_sci.c +--- linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/ec_sci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/ec_sci.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,1026 @@ ++/* ++ * EC(Embedded Controller) KB3310B SCI EVENT management driver on Linux ++ * Author : liujl ++ * Date : 2008-10-22 ++ * ++ * NOTE : Until now, I have no idea for setting the interrupt to edge sensitive ++ * mode, amd's help should be needed for handling this problem ++ * So, I assume that the interrupt width is 120us ++ */ + -+ if ((packet.cmd_sts & TITAN_GE_RX_PERR) || -+ (packet.cmd_sts & TITAN_GE_RX_OVERFLOW_ERROR) || -+ (packet.cmd_sts & TITAN_GE_RX_TRUNC) || -+ (packet.cmd_sts & TITAN_GE_RX_CRC_ERROR)) { -+ stats->rx_dropped++; -+ dev_kfree_skb_any(skb); ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+ continue; -+ } -+ /* -+ * Either support fast path or slow path. Decision -+ * making can really slow down the performance. The -+ * idea is to cut down the number of checks and improve -+ * the fastpath. -+ */ ++#include + -+ skb_put(skb, packet.len - 2); ++#include "ec.h" ++#include "ec_misc_fn.h" + -+ /* -+ * Increment data pointer by two since thats where -+ * the MAC starts -+ */ -+ skb_reserve(skb, 2); -+ skb->protocol = eth_type_trans(skb, netdev); -+ netif_receive_skb(skb); -+ -+ if (titan_ge_eth->rx_threshold > RX_THRESHOLD) { -+ ack = titan_ge_rx_task(netdev, titan_ge_eth); -+ TITAN_GE_WRITE((0x5048 + (port_num << 8)), ack); -+ titan_ge_eth->rx_threshold = 0; -+ } else -+ titan_ge_eth->rx_threshold++; ++/* inode information */ ++#define EC_SCI_MINOR_DEV MISC_DYNAMIC_MINOR ++#define EC_SCI_DEV "sci" ++#define SCI_IRQ_NUM 0x0A ++#define CS5536_GPIO_SIZE 256 + -+ if (titan_ge_eth->tx_threshold > TX_THRESHOLD) { -+ titan_ge_eth->tx_threshold = 0; -+ titan_ge_free_tx_queue(titan_ge_eth); -+ } -+ else -+ titan_ge_eth->tx_threshold++; ++/* ec delay time 500us for register and status access */ ++/* unit : us */ ++#define EC_REG_DELAY 300 + -+ } -+ return received_packets; -+} ++struct ec_sci_reg { ++ u32 addr; ++ u8 val; ++}; ++struct ec_sci_reg ecreg; + ++struct sci_device { ++ /* the sci number get from ec */ ++ unsigned char sci_number; + -+/* -+ * Enable the Rx side interrupts -+ */ -+static void titan_ge_enable_int(unsigned int port_num, -+ titan_ge_port_info *titan_ge_eth, -+ struct net_device *netdev) -+{ -+ unsigned long reg_data = TITAN_GE_READ(TITAN_GE_INTR_XDMA_IE); ++ /* sci count */ ++ unsigned char sci_num_array[SCI_MAX_EVENT_COUNT]; + -+ if (port_num == 0) -+ reg_data |= 0x3; -+ if (port_num == 1) -+ reg_data |= 0x300; -+ if (port_num == 2) -+ reg_data |= 0x30000; ++ /* irq relative */ ++ unsigned char irq; ++ unsigned char irq_data; + -+ /* Re-enable interrupts */ -+ TITAN_GE_WRITE(TITAN_GE_INTR_XDMA_IE, reg_data); -+} ++ /* device name */ ++ unsigned char name[10]; + -+/* -+ * Main function to handle the polling for Rx side NAPI. -+ * Receive interrupts have been disabled at this point. -+ * The poll schedules the transmit followed by receive. -+ */ -+static int titan_ge_poll(struct net_device *netdev, int *budget) -+{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); -+ int port_num = titan_ge_eth->port_num; -+ int work_done = 0; -+ unsigned long flags, status; ++ /* gpio base registers and length */ ++ unsigned long gpio_base; ++ unsigned long gpio_size; + -+ titan_ge_eth->rx_work_limit = *budget; -+ if (titan_ge_eth->rx_work_limit > netdev->quota) -+ titan_ge_eth->rx_work_limit = netdev->quota; ++ /* lock & wait_queue */ ++ wait_queue_head_t wq; ++ spinlock_t lock; + -+ do { -+ /* Do the transmit cleaning work here */ -+ titan_ge_free_tx_queue(titan_ge_eth); ++ /* storage initial value of sci status register ++ * sci_init_value[0] as brightness ++ * sci_init_value[1] as volume ++ */ ++ unsigned char sci_init_value[2]; ++}; ++struct sci_device *sci_device; ++ ++#ifdef CONFIG_PROC_FS ++static ssize_t sci_proc_read(struct file *file, char *buf, size_t len, ++ loff_t *ppos); ++static ssize_t sci_proc_write(struct file *file, const char *buf, size_t len, ++ loff_t *ppos); ++static unsigned int sci_poll(struct file *fp, poll_table *wait); ++static struct proc_dir_entry *sci_proc_entry; ++static const struct file_operations sci_proc_fops = { ++ .read = sci_proc_read, ++ .poll = sci_poll, ++ .write = sci_proc_write, ++}; + -+ /* Ack the Rx interrupts */ -+ if (port_num == 0) -+ TITAN_GE_WRITE(TITAN_GE_INTR_XDMA_CORE_A, 0x3); -+ if (port_num == 1) -+ TITAN_GE_WRITE(TITAN_GE_INTR_XDMA_CORE_A, 0x300); -+ if (port_num == 2) -+ TITAN_GE_WRITE(TITAN_GE_INTR_XDMA_CORE_A, 0x30000); ++#define SCI_ACTION_COUNT 15 ++#define SCI_ACTION_WIDTH 14 ++char sci_action[SCI_ACTION_COUNT][SCI_ACTION_WIDTH] = { ++ "DISPLAY : LCD", ++ "DISPLAY : CRT", ++ "DISPLAY : ALL", ++ "DISPLAY : CHG", ++ "AUDIO : CHG", ++ "MACHINE : OFF", ++ "MACHINE : RES", ++ "CAMERA : ON", ++ "CAMERA : OFF", ++ "LCDLED : ON", ++ "LCDLED : OFF", ++ "LCDBL : ON", ++ "LCDBL : OFF", ++ "NONE", ++ "NONE" ++}; + -+ work_done += titan_ge_receive_queue(netdev, 0); ++static enum { ++ CMD_DISPLAY_LCD = 0, ++ CMD_DISPLAY_CRT, ++ CMD_DISPLAY_ALL, ++ CMD_DISPLAY_CHANGE_BRIGHTNESS, ++ CMD_AUDIO_CHANGE_VOLUME, ++ CMD_MACHINE_OFF, ++ CMD_MACHINE_RESET, ++ CMD_CAMERA_ON, ++ CMD_CAMERA_OFF, ++ CMD_LCDLED_PWRON, ++ CMD_LCDLED_PWROFF, ++ CMD_LCDBL_ON, ++ CMD_LCDBL_OFF, ++ CMD_NONE ++} sci_cmd; + -+ /* Out of quota and there is work to be done */ -+ if (titan_ge_eth->rx_work_limit < 0) -+ goto not_done; ++#endif + -+ /* Receive alloc_skb could lead to OOM */ -+ if (oom_flag == 1) { -+ oom_flag = 0; -+ goto oom; -+ } ++static void sci_display_lcd(void) ++{ ++ unsigned char value; + -+ status = TITAN_GE_READ(TITAN_GE_INTR_XDMA_CORE_A); -+ } while (status & 0x30300); ++ outb(0x21, 0x3c4); ++ value = inb(0x3c5); ++ value |= (1 << 7); ++ outb(0x21, 0x3c4); ++ outb(value, 0x3c5); + -+ /* If we are here, then no more interrupts to process */ -+ goto done; ++ outb(0x31, 0x3c4); ++ value = inb(0x3c5); ++ value = (value & 0xf8) | 0x01; ++ outb(0x31, 0x3c4); ++ outb(value, 0x3c5); + -+not_done: -+ *budget -= work_done; -+ netdev->quota -= work_done; -+ return 1; ++ return; ++} + -+oom: -+ printk(KERN_ERR "OOM \n"); -+ netif_rx_complete(netdev); -+ return 0; ++static void sci_display_crt(void) ++{ ++ unsigned char value; + -+done: -+ /* -+ * No more packets on the poll list. Turn the interrupts -+ * back on and we should be able to catch the new -+ * packets in the interrupt handler -+ */ -+ if (!work_done) -+ work_done = 1; ++ outb(0x21, 0x3c4); ++ value = inb(0x3c5); ++ value &= ~(1 << 7); ++ outb(0x21, 0x3c4); ++ outb(value, 0x3c5); + -+ *budget -= work_done; -+ netdev->quota -= work_done; ++ outb(0x31, 0x3c4); ++ value = inb(0x3c5); ++ value = (value & 0xf8) | 0x02; ++ outb(0x31, 0x3c4); ++ outb(value, 0x3c5); + -+ spin_lock_irqsave(&titan_ge_eth->lock, flags); ++ return; ++} + -+ /* Remove us from the poll list */ -+ netif_rx_complete(netdev); ++static void sci_display_all(void) ++{ ++ unsigned char value; + -+ /* Re-enable interrupts */ -+ titan_ge_enable_int(port_num, titan_ge_eth, netdev); ++ outb(0x21, 0x3c4); ++ value = inb(0x3c5); ++ value &= ~(1 << 7); ++ outb(0x21, 0x3c4); ++ outb(value, 0x3c5); + -+ spin_unlock_irqrestore(&titan_ge_eth->lock, flags); ++ outb(0x31, 0x3c4); ++ value = inb(0x3c5); ++ value = (value & 0xf8) | 0x03; ++ outb(0x31, 0x3c4); ++ outb(value, 0x3c5); + -+ return 0; ++ return; +} + -+/* -+ * Close the network device -+ */ -+int titan_ge_stop(struct net_device *netdev) ++static void sci_lcd_op(unsigned char flag) +{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); ++ unsigned char value; ++ ++ /* default display crt */ ++ outb(0x21, 0x3c4); ++ value = inb(0x3c5); ++ value &= ~(1 << 7); ++ outb(0x21, 0x3c4); ++ outb(value, 0x3c5); ++ ++ if (flag == CMD_LCDLED_PWRON) { ++ /* open lcd output */ ++ outb(0x31, 0x3c4); ++ value = inb(0x3c5); ++ value = (value & 0xf8) | 0x03; ++ outb(0x31, 0x3c4); ++ outb(value, 0x3c5); ++ } else if (flag == CMD_LCDLED_PWROFF) { ++ /* close lcd output */ ++ outb(0x31, 0x3c4); ++ value = inb(0x3c5); ++ value = (value & 0xf8) | 0x02; ++ outb(0x31, 0x3c4); ++ outb(value, 0x3c5); ++ } else if (flag == CMD_LCDBL_ON) ++ /* LCD backlight on */ ++ ec_write(REG_BACKLIGHT_CTRL, BIT_BACKLIGHT_ON); ++ else if (flag == CMD_LCDBL_OFF) ++ /* LCD backlight off */ ++ ec_write(REG_BACKLIGHT_CTRL, BIT_BACKLIGHT_OFF); + -+ spin_lock_irq(&(titan_ge_eth->lock)); -+ titan_ge_eth_stop(netdev); -+ free_irq(netdev->irq, netdev); -+ spin_unlock_irq(&titan_ge_eth->lock); ++ return; ++} + -+ return TITAN_OK; ++static void sci_display_change_brightness(void) ++{ ++ ec_write(REG_DISPLAY_BRIGHTNESS, FLAG_DISPLAY_BRIGHTNESS_LEVEL_4); ++ return; +} + -+/* -+ * Free the Tx ring -+ */ -+static void titan_ge_free_tx_rings(struct net_device *netdev) ++static void sci_audio_change_volume(void) +{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); -+ unsigned int port_num = titan_ge_eth->port_num; -+ unsigned int curr; -+ unsigned long reg_data; ++ ec_write(REG_AUDIO_VOLUME, FLAG_AUDIO_VOLUME_LEVEL_5); ++ return; ++} + -+ /* Stop the Tx DMA */ -+ reg_data = TITAN_GE_READ(TITAN_GE_CHANNEL0_CONFIG + -+ (port_num << 8)); -+ reg_data |= 0xc0000000; -+ TITAN_GE_WRITE((TITAN_GE_CHANNEL0_CONFIG + -+ (port_num << 8)), reg_data); ++static void sci_camera_on_off(void) ++{ ++ unsigned char val; ++ val = ec_read(REG_CAMERA_CONTROL); ++ ec_write(REG_CAMERA_CONTROL, val | (1 << 1)); ++ return; ++} + -+ /* Disable the TMAC */ -+ reg_data = TITAN_GE_READ(TITAN_GE_TMAC_CONFIG_1 + -+ (port_num << 12)); -+ reg_data &= ~(0x00000001); -+ TITAN_GE_WRITE((TITAN_GE_TMAC_CONFIG_1 + -+ (port_num << 12)), reg_data); ++static void sci_machine_off(void) ++{ ++#ifdef CONFIG_64BIT ++ /* cpu-gpio0 output low */ ++ *((unsigned int *)(0xffffffffbfe0011c)) &= ~0x00000001; ++ /* cpu-gpio0 as output */ ++ *((unsigned int *)(0xffffffffbfe00120)) &= ~0x00000001; ++#else ++ /* cpu-gpio0 output low */ ++ *((unsigned int *)(0xbfe0011c)) &= ~0x00000001; ++ /* cpu-gpio0 as output */ ++ *((unsigned int *)(0xbfe00120)) &= ~0x00000001; ++#endif /* end ifdef CONFIG_64BIT */ ++ return; ++} + -+ for (curr = 0; -+ (titan_ge_eth->tx_ring_skbs) && (curr < TITAN_GE_TX_QUEUE); -+ curr++) { -+ if (titan_ge_eth->tx_skb[curr]) { -+ dev_kfree_skb(titan_ge_eth->tx_skb[curr]); -+ titan_ge_eth->tx_ring_skbs--; -+ } -+ } ++static void sci_machine_reset(void) ++{ ++ ec_write(REG_RESET, BIT_RESET_ON); ++ return; ++} + -+ if (titan_ge_eth->tx_ring_skbs != 0) -+ printk -+ ("%s: Error on Tx descriptor free - could not free %d" -+ " descriptors\n", netdev->name, -+ titan_ge_eth->tx_ring_skbs); ++/* static const char driver_version[] = "1.0"; */ ++static const char driver_version[] = VERSION; + -+#ifndef TITAN_RX_RING_IN_SRAM -+ dma_free_coherent(&titan_ge_device[port_num]->dev, -+ titan_ge_eth->tx_desc_area_size, -+ (void *) titan_ge_eth->tx_desc_area, -+ titan_ge_eth->tx_dma); -+#endif -+} ++#ifdef CONFIG_PROC_FS ++#define PROC_BUF_SIZE 128 ++unsigned char proc_buf[PROC_BUF_SIZE]; + +/* -+ * Free the Rx ring ++ * sci_proc_read : ++ * read information from sci device and suppied to upper layer ++ * The format is as following : ++ * driver_version 1.0 ++ * DISPLAY BRIGHTNESS INCREASE ++ * DISPLAY BRIGHTNESS DECREASE ++ * AUDIO VOLUME INCREASE ++ * AUDIO VOLUME DECREASE ++ * MUTE 0x00 close, 0x01 open ++ * WLAN 0x00 close, 0x01 open ++ * LID 0x00 close, 0x01 open ++ * DISPLAY TOGGLE ++ * BLACK SCREEN ++ * SLEEP ++ * OVER TEMPERATURE ++ * CRT DETECT ++ * CAMERA 0x00 close, 0x01 open ++ * USB OC2 ++ * USB OC0 ++ * BAT IN ++ * AC IN ++ * INIT CAP ++ * CHARGE MODE ++ * STOP CHARGE ++ * BAT LOW ++ * BAT FULL + */ -+static void titan_ge_free_rx_rings(struct net_device *netdev) ++static ssize_t sci_proc_read(struct file *file, char *buf, size_t len, ++ loff_t *ppos) +{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); -+ unsigned int port_num = titan_ge_eth->port_num; -+ unsigned int curr; -+ unsigned long reg_data; ++ unsigned char event[SCI_MAX_EVENT_COUNT]; ++ int ret = 0; ++ int i; ++ int count = 0; ++ DECLARE_WAITQUEUE(wait, current); + -+ /* Stop the Rx DMA */ -+ reg_data = TITAN_GE_READ(TITAN_GE_CHANNEL0_CONFIG + -+ (port_num << 8)); -+ reg_data |= 0x000c0000; -+ TITAN_GE_WRITE((TITAN_GE_CHANNEL0_CONFIG + -+ (port_num << 8)), reg_data); ++ PRINTK_DBG("0 irq_data %d\n", sci_device->irq_data); + -+ /* Disable the RMAC */ -+ reg_data = TITAN_GE_READ(TITAN_GE_RMAC_CONFIG_1 + -+ (port_num << 12)); -+ reg_data &= ~(0x00000001); -+ TITAN_GE_WRITE((TITAN_GE_RMAC_CONFIG_1 + -+ (port_num << 12)), reg_data); ++ if (sci_device->irq_data == 0) { ++ add_wait_queue(&(sci_device->wq), &wait); + -+ for (curr = 0; -+ titan_ge_eth->rx_ring_skbs && (curr < TITAN_GE_RX_QUEUE); -+ curr++) { -+ if (titan_ge_eth->rx_skb[curr]) { -+ dev_kfree_skb(titan_ge_eth->rx_skb[curr]); -+ titan_ge_eth->rx_ring_skbs--; ++ while (!sci_device->irq_data) { ++ set_current_state(TASK_INTERRUPTIBLE); ++ schedule(); + } ++ remove_wait_queue(&(sci_device->wq), &wait); + } + -+ if (titan_ge_eth->rx_ring_skbs != 0) -+ printk(KERN_ERR -+ "%s: Error in freeing Rx Ring. %d skb's still" -+ " stuck in RX Ring - ignoring them\n", netdev->name, -+ titan_ge_eth->rx_ring_skbs); -+ -+#ifndef TITAN_RX_RING_IN_SRAM -+ dma_free_coherent(&titan_ge_device[port_num]->dev, -+ titan_ge_eth->rx_desc_area_size, -+ (void *) titan_ge_eth->rx_desc_area, -+ titan_ge_eth->rx_dma); -+#endif -+} -+ -+/* -+ * Actually does the stop of the Ethernet device -+ */ -+static void titan_ge_eth_stop(struct net_device *netdev) -+{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); -+ -+ netif_stop_queue(netdev); -+ -+ titan_ge_port_reset(titan_ge_eth->port_num); ++ PRINTK_DBG("1 irq_data %d\n", sci_device->irq_data); ++ __set_current_state(TASK_RUNNING); ++ ++ for (i = 0; i < SCI_MAX_EVENT_COUNT; i++) ++ event[i] = sci_device->sci_num_array[i]; ++ ++ ret = sprintf(proc_buf, ++ "%s 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x " ++ "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x " ++ "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", ++ driver_version, event[SCI_INDEX_DISPLAY_BRIGHTNESS_INC], ++ event[SCI_INDEX_DISPLAY_BRIGHTNESS_DEC], ++ event[SCI_INDEX_AUDIO_VOLUME_INC], ++ event[SCI_INDEX_AUDIO_VOLUME_DEC], ++ event[SCI_INDEX_AUDIO_MUTE], event[SCI_INDEX_WLAN], ++ event[SCI_INDEX_LID], event[SCI_INDEX_DISPLAY_TOGGLE], ++ event[SCI_INDEX_BLACK_SCREEN], event[SCI_INDEX_SLEEP], ++ event[SCI_INDEX_OVERTEMP], event[SCI_INDEX_CRT_DETECT], ++ event[SCI_INDEX_CAMERA], event[SCI_INDEX_USB_OC2], ++ event[SCI_INDEX_USB_OC0], ++ (event[SCI_INDEX_AC_BAT] & 0x01) >> BIT_AC_BAT_BAT_IN, ++ (event[SCI_INDEX_AC_BAT] & 0x02) >> BIT_AC_BAT_AC_IN, ++ (event[SCI_INDEX_AC_BAT] & 0x04) >> BIT_AC_BAT_INIT_CAP, ++ (event[SCI_INDEX_AC_BAT] & 0x08) >> ++ BIT_AC_BAT_CHARGE_MODE, ++ (event[SCI_INDEX_AC_BAT] & 0x10) >> ++ BIT_AC_BAT_STOP_CHARGE, ++ (event[SCI_INDEX_AC_BAT] & 0x20) >> BIT_AC_BAT_BAT_LOW, ++ (event[SCI_INDEX_AC_BAT] & 0x40) >> BIT_AC_BAT_BAT_FULL); ++ ++ count = strlen(proc_buf); ++ sci_device->irq_data = 0; ++ ++ if (len < count) ++ return -ENOMEM; ++ if (PROC_BUF_SIZE < count) ++ return -ENOMEM; + -+ titan_ge_free_tx_rings(netdev); -+ titan_ge_free_rx_rings(netdev); ++ if (copy_to_user(buf, proc_buf, count)) ++ return -EFAULT; + -+ /* Disable the Tx and Rx Interrupts for all channels */ -+ TITAN_GE_WRITE(TITAN_GE_INTR_XDMA_IE, 0x0); ++ return count; +} + +/* -+ * Update the MAC address. Note that we have to write the -+ * address in three station registers, 16 bits each. And this -+ * has to be done for TMAC and RMAC ++ * sci_proc_write : ++ * get the upper layer's action and take action. + */ -+static void titan_ge_update_mac_address(struct net_device *netdev) ++static ssize_t sci_proc_write(struct file *file, const char *buf, size_t len, ++ loff_t *ppos) +{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); -+ unsigned int port_num = titan_ge_eth->port_num; -+ u8 p_addr[6]; -+ -+ memcpy(titan_ge_eth->port_mac_addr, netdev->dev_addr, 6); -+ memcpy(p_addr, netdev->dev_addr, 6); -+ -+ /* Update the Address Filtering Match tables */ -+ titan_ge_update_afx(titan_ge_eth); -+ -+ printk("Station MAC : %d %d %d %d %d %d \n", -+ p_addr[5], p_addr[4], p_addr[3], -+ p_addr[2], p_addr[1], p_addr[0]); ++ int i; + -+ /* Set the MAC address here for TMAC and RMAC */ -+ TITAN_GE_WRITE((TITAN_GE_TMAC_STATION_HI + (port_num << 12)), -+ ((p_addr[5] << 8) | p_addr[4])); -+ TITAN_GE_WRITE((TITAN_GE_TMAC_STATION_MID + (port_num << 12)), -+ ((p_addr[3] << 8) | p_addr[2])); -+ TITAN_GE_WRITE((TITAN_GE_TMAC_STATION_LOW + (port_num << 12)), -+ ((p_addr[1] << 8) | p_addr[0])); ++ if (len > PROC_BUF_SIZE) ++ return -ENOMEM; ++ if (copy_from_user(proc_buf, buf, len)) ++ return -EFAULT; ++ proc_buf[len] = '\0'; ++ ++ PRINTK_DBG("proc_buf : %s\n", proc_buf); ++ for (i = 0; i < SCI_ACTION_COUNT; i++) { ++ if (strncmp(proc_buf, sci_action[i], strlen(sci_action[i])) == ++ 0) { ++ sci_cmd = i; ++ break; ++ } ++ } ++ if (i == SCI_ACTION_COUNT) ++ sci_cmd = CMD_NONE; ++ PRINTK_DBG("sci_cmd: %d\n", sci_cmd); ++ switch (sci_cmd) { ++ case CMD_DISPLAY_LCD: ++ sci_display_lcd(); ++ PRINTK_DBG(KERN_DEBUG "CMD_DISPLAY_LCD"); ++ break; ++ case CMD_DISPLAY_CRT: ++ sci_display_crt(); ++ PRINTK_DBG(KERN_DEBUG "CMD_DISPLAY_CRT"); ++ break; ++ case CMD_DISPLAY_ALL: ++ sci_display_all(); ++ PRINTK_DBG(KERN_DEBUG "CMD_DISPLAY_ALL"); ++ break; ++ case CMD_DISPLAY_CHANGE_BRIGHTNESS: ++ sci_display_change_brightness(); ++ PRINTK_DBG(KERN_DEBUG "CMD_DISPLAY_CHANGE_BRIGHTNESS"); ++ break; ++ case CMD_AUDIO_CHANGE_VOLUME: ++ sci_audio_change_volume(); ++ PRINTK_DBG(KERN_DEBUG "CMD_AUDIO_CHANGE_VOLUME"); ++ break; ++ case CMD_MACHINE_OFF: ++ sci_machine_off(); ++ PRINTK_DBG(KERN_DEBUG "CMD_MACHINE_OFF"); ++ break; ++ case CMD_MACHINE_RESET: ++ sci_machine_reset(); ++ PRINTK_DBG(KERN_DEBUG "CMD_MACHINE_RESET"); ++ break; ++ case CMD_CAMERA_ON: ++ sci_camera_on_off(); ++ PRINTK_DBG(KERN_DEBUG "CMD_CAMERA_ON"); ++ break; ++ case CMD_CAMERA_OFF: ++ sci_camera_on_off(); ++ PRINTK_DBG(KERN_DEBUG "CMD_CAMERA_OFF"); ++ break; ++ case CMD_LCDLED_PWRON: ++ sci_lcd_op(CMD_LCDLED_PWRON); ++ PRINTK_DBG(KERN_DEBUG "CMD_LCDLED_PWRON"); ++ break; ++ case CMD_LCDLED_PWROFF: ++ sci_lcd_op(CMD_LCDLED_PWROFF); ++ PRINTK_DBG(KERN_DEBUG "CMD_LCDLED_PWROFF"); ++ break; ++ case CMD_LCDBL_ON: ++ sci_lcd_op(CMD_LCDBL_ON); ++ PRINTK_DBG(KERN_DEBUG "CMD_LCDBL_ON"); ++ break; ++ case CMD_LCDBL_OFF: ++ sci_lcd_op(CMD_LCDBL_OFF); ++ PRINTK_DBG(KERN_DEBUG "CMD_LCDBL_OFF"); ++ break; ++ default: ++ printk(KERN_ERR "EC SCI : Not supported cmd.\n"); ++ return -EINVAL; ++ } + -+ TITAN_GE_WRITE((TITAN_GE_RMAC_STATION_HI + (port_num << 12)), -+ ((p_addr[5] << 8) | p_addr[4])); -+ TITAN_GE_WRITE((TITAN_GE_RMAC_STATION_MID + (port_num << 12)), -+ ((p_addr[3] << 8) | p_addr[2])); -+ TITAN_GE_WRITE((TITAN_GE_RMAC_STATION_LOW + (port_num << 12)), -+ ((p_addr[1] << 8) | p_addr[0])); ++ return len; +} ++#endif + +/* -+ * Set the MAC address of the Ethernet device ++ * sci_query_event_num : ++ * using query command to ec to get the proper event number + */ -+static int titan_ge_set_mac_address(struct net_device *dev, void *addr) ++static int sci_query_event_num(void) +{ -+ titan_ge_port_info *tp = netdev_priv(dev); -+ struct sockaddr *sa = addr; -+ -+ memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); -+ -+ spin_lock_irq(&tp->lock); -+ titan_ge_update_mac_address(dev); -+ spin_unlock_irq(&tp->lock); ++ int ret = 0; + -+ return 0; ++ ret = ec_query_seq(CMD_GET_EVENT_NUM); ++ return ret; +} + +/* -+ * Get the Ethernet device stats ++ * sci_get_event_num : ++ * get sci event number from ec ++ * NOTE : this routine must follow the sci_query_event_num ++ * function in the interrupt + */ -+static struct net_device_stats *titan_ge_get_stats(struct net_device *netdev) ++int sci_get_event_num(void) +{ -+ titan_ge_port_info *titan_ge_eth = netdev_priv(netdev); ++ int timeout = 100; ++ unsigned char value; ++ unsigned char status; ++ ++ udelay(EC_REG_DELAY); ++ status = inb(EC_STS_PORT); ++ udelay(EC_REG_DELAY); ++ while (timeout--) { ++ if (!(status & (1 << 0))) { ++ status = inb(EC_STS_PORT); ++ udelay(EC_REG_DELAY); ++ continue; ++ } ++ break; ++ } ++ if (timeout <= 0) { ++ PRINTK_DBG("fixup sci : get event number timeout.\n"); ++ return -EINVAL; ++ } ++ value = inb(EC_DAT_PORT); ++ udelay(EC_REG_DELAY); + -+ return &titan_ge_eth->stats; ++ return value; +} ++EXPORT_SYMBOL(sci_get_event_num); + +/* -+ * Initialize the Rx descriptor ring for the Titan Ge ++ * sci_parse_num : ++ * parse the event number routine, and store all the information ++ * to the sci_num_array[] for upper layer using + */ -+static int titan_ge_init_rx_desc_ring(titan_ge_port_info * titan_eth_port, -+ int rx_desc_num, -+ int rx_buff_size, -+ unsigned long rx_desc_base_addr, -+ unsigned long rx_buff_base_addr, -+ unsigned long rx_dma) -+{ -+ volatile titan_ge_rx_desc *rx_desc; -+ unsigned long buffer_addr; -+ int index; -+ unsigned long titan_ge_rx_desc_bus = rx_dma; -+ -+ buffer_addr = rx_buff_base_addr; -+ rx_desc = (titan_ge_rx_desc *) rx_desc_base_addr; -+ -+ /* Check alignment */ -+ if (rx_buff_base_addr & 0xF) -+ return 0; -+ -+ /* Check Rx buffer size */ -+ if ((rx_buff_size < 8) || (rx_buff_size > TITAN_GE_MAX_RX_BUFFER)) -+ return 0; -+ -+ /* 64-bit alignment -+ if ((rx_buff_base_addr + rx_buff_size) & 0x7) -+ return 0; */ -+ -+ /* Initialize the Rx desc ring */ -+ for (index = 0; index < rx_desc_num; index++) { -+ titan_ge_rx_desc_bus += sizeof(titan_ge_rx_desc); -+ rx_desc[index].cmd_sts = 0; -+ rx_desc[index].buffer_addr = buffer_addr; -+ titan_eth_port->rx_skb[index] = NULL; -+ buffer_addr += rx_buff_size; ++static int sci_parse_num(struct sci_device *sci_device) ++{ ++ unsigned char val; ++ ++ sci_device->sci_num_array[SCI_INDEX_DISPLAY_TOGGLE] = 0x0; ++ sci_device->sci_num_array[SCI_INDEX_SLEEP] = 0x0; ++ sci_device->sci_num_array[SCI_INDEX_DISPLAY_BRIGHTNESS_DEC] = 0; ++ sci_device->sci_num_array[SCI_INDEX_DISPLAY_BRIGHTNESS_INC] = 0; ++ sci_device->sci_num_array[SCI_INDEX_AUDIO_VOLUME_INC] = 0; ++ sci_device->sci_num_array[SCI_INDEX_AUDIO_VOLUME_DEC] = 0; ++ ++ sci_device->sci_num_array[SCI_INDEX_CAMERA] = 0x0; ++ sci_device->sci_num_array[SCI_INDEX_WLAN] = ec_read(REG_WLAN_STATUS); ++ sci_device->sci_num_array[SCI_INDEX_AUDIO_MUTE] = ++ ec_read(REG_AUDIO_MUTE); ++ sci_device->sci_num_array[SCI_INDEX_BLACK_SCREEN] = ++ ec_read(REG_DISPLAY_LCD); ++ sci_device->sci_num_array[SCI_INDEX_CRT_DETECT] = ++ ec_read(REG_CRT_DETECT); ++ if (ec_read(REG_BAT_POWER) & BIT_BAT_POWER_ACIN) { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] |= ++ 1 << BIT_AC_BAT_AC_IN; ++ } else { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] &= ++ ~(1 << BIT_AC_BAT_AC_IN); + } + -+ titan_eth_port->rx_curr_desc_q = 0; -+ titan_eth_port->rx_used_desc_q = 0; ++ switch (sci_device->sci_number) { ++ case SCI_EVENT_NUM_LID: ++ sci_device->sci_num_array[SCI_INDEX_LID] = ++ ec_read(REG_LID_DETECT); ++ break; ++ case SCI_EVENT_NUM_DISPLAY_TOGGLE: ++ sci_device->sci_num_array[SCI_INDEX_DISPLAY_TOGGLE] = 0x01; ++ break; ++ case SCI_EVENT_NUM_SLEEP: ++ sci_device->sci_num_array[SCI_INDEX_SLEEP] = 0x01; ++ break; ++ case SCI_EVENT_NUM_OVERTEMP: ++ sci_device->sci_num_array[SCI_INDEX_OVERTEMP] = ++ (ec_read(REG_BAT_CHARGE_STATUS) & ++ BIT_BAT_CHARGE_STATUS_OVERTEMP) >> 2; ++ break; ++ case SCI_EVENT_NUM_CRT_DETECT: ++ sci_device->sci_num_array[SCI_INDEX_CRT_DETECT] = ++ ec_read(REG_CRT_DETECT); ++ break; ++ case SCI_EVENT_NUM_CAMERA: ++ sci_device->sci_num_array[SCI_INDEX_CAMERA] = 0x1; ++ break; ++ case SCI_EVENT_NUM_USB_OC2: ++ sci_device->sci_num_array[SCI_INDEX_USB_OC2] = ++ ec_read(REG_USB2_FLAG); ++ break; ++ case SCI_EVENT_NUM_USB_OC0: ++ sci_device->sci_num_array[SCI_INDEX_USB_OC0] = ++ ec_read(REG_USB0_FLAG); ++ break; ++ case SCI_EVENT_NUM_AC_BAT: ++ if (ec_read(REG_BAT_STATUS) & BIT_BAT_STATUS_IN) { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] |= ++ 1 << BIT_AC_BAT_BAT_IN; ++ } else { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] &= ++ ~(1 << BIT_AC_BAT_BAT_IN); ++ } + -+ titan_eth_port->rx_desc_area = (titan_ge_rx_desc *) rx_desc_base_addr; -+ titan_eth_port->rx_desc_area_size = -+ rx_desc_num * sizeof(titan_ge_rx_desc); ++ if (ec_read(REG_BAT_POWER) & BIT_BAT_POWER_ACIN) { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] |= ++ 1 << BIT_AC_BAT_AC_IN; ++ } else { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] &= ++ ~(1 << BIT_AC_BAT_AC_IN); ++ } + -+ titan_eth_port->rx_dma = rx_dma; ++ /* init_bat_cap will not be included here. */ + -+ return TITAN_OK; -+} ++ if (ec_read(REG_BAT_CHARGE_STATUS) & ++ BIT_BAT_CHARGE_STATUS_PRECHG) { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] |= ++ 1 << BIT_AC_BAT_CHARGE_MODE; ++ } else { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] &= ++ ~(1 << BIT_AC_BAT_CHARGE_MODE); ++ } + -+/* -+ * Initialize the Tx descriptor ring. Descriptors in the SRAM -+ */ -+static int titan_ge_init_tx_desc_ring(titan_ge_port_info * titan_ge_port, -+ int tx_desc_num, -+ unsigned long tx_desc_base_addr, -+ unsigned long tx_dma) -+{ -+ titan_ge_tx_desc *tx_desc; -+ int index; -+ unsigned long titan_ge_tx_desc_bus = tx_dma; ++ if (ec_read(REG_BAT_STATE) & BIT_BAT_STATE_DISCHARGING) { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] |= ++ 1 << BIT_AC_BAT_STOP_CHARGE; ++ } else { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] &= ++ ~(1 << BIT_AC_BAT_STOP_CHARGE); ++ } + -+ if (tx_desc_base_addr & 0xF) -+ return 0; ++ if (ec_read(REG_BAT_STATUS) & BIT_BAT_STATUS_LOW) { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] |= ++ 1 << BIT_AC_BAT_BAT_LOW; ++ } else { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] &= ++ ~(1 << BIT_AC_BAT_BAT_LOW); ++ } + -+ tx_desc = (titan_ge_tx_desc *) tx_desc_base_addr; ++ if (ec_read(REG_BAT_STATUS) & BIT_BAT_STATUS_FULL) { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] |= ++ 1 << BIT_AC_BAT_BAT_FULL; ++ } else { ++ sci_device->sci_num_array[SCI_INDEX_AC_BAT] &= ++ ~(1 << BIT_AC_BAT_BAT_FULL); ++ } ++ break; ++ case SCI_EVENT_NUM_DISPLAY_BRIGHTNESS: ++ val = ec_read(REG_DISPLAY_BRIGHTNESS); ++ if ((val == 0x00) || (val < sci_device->sci_init_value[0])) { ++ sci_device-> ++ sci_num_array[SCI_INDEX_DISPLAY_BRIGHTNESS_DEC] = 1; ++ sci_device->sci_init_value[0] = val; ++ } else if ((val == 0x08) ++ || (val > sci_device->sci_init_value[0])) { ++ sci_device-> ++ sci_num_array[SCI_INDEX_DISPLAY_BRIGHTNESS_INC] = 1; ++ sci_device->sci_init_value[0] = val; ++ } ++ break; ++ case SCI_EVENT_NUM_AUDIO_VOLUME: ++ val = ec_read(REG_AUDIO_VOLUME); ++ if ((val == 0x00) || (val < sci_device->sci_init_value[1])) { ++ sci_device->sci_num_array[SCI_INDEX_AUDIO_VOLUME_DEC] = ++ 1; ++ sci_device->sci_init_value[1] = val; ++ } else if ((val == 0x0a) ++ || (val > sci_device->sci_init_value[1])) { ++ sci_device->sci_num_array[SCI_INDEX_AUDIO_VOLUME_INC] = ++ 1; ++ sci_device->sci_init_value[1] = val; ++ } ++ break; ++ case SCI_EVENT_NUM_WLAN: ++ sci_device->sci_num_array[SCI_INDEX_WLAN] = ++ ec_read(REG_WLAN_STATUS); ++ break; ++ case SCI_EVENT_NUM_AUDIO_MUTE: ++ sci_device->sci_num_array[SCI_INDEX_AUDIO_MUTE] = ++ ec_read(REG_AUDIO_MUTE); ++ break; ++ case SCI_EVENT_NUM_BLACK_SCREEN: ++ sci_device->sci_num_array[SCI_INDEX_BLACK_SCREEN] = ++ ec_read(REG_DISPLAY_LCD); ++ break; + -+ for (index = 0; index < tx_desc_num; index++) { -+ titan_ge_port->tx_dma_array[index] = -+ (dma_addr_t) titan_ge_tx_desc_bus; -+ titan_ge_tx_desc_bus += sizeof(titan_ge_tx_desc); -+ tx_desc[index].cmd_sts = 0x0000; -+ tx_desc[index].buffer_len = 0; -+ tx_desc[index].buffer_addr = 0x00000000; -+ titan_ge_port->tx_skb[index] = NULL; ++ default: ++ PRINTK_DBG(KERN_ERR "EC SCI : not supported SCI NUMBER.\n"); ++ return -EINVAL; ++ break; + } + -+ titan_ge_port->tx_curr_desc_q = 0; -+ titan_ge_port->tx_used_desc_q = 0; -+ -+ titan_ge_port->tx_desc_area = (titan_ge_tx_desc *) tx_desc_base_addr; -+ titan_ge_port->tx_desc_area_size = -+ tx_desc_num * sizeof(titan_ge_tx_desc); -+ -+ titan_ge_port->tx_dma = tx_dma; -+ return TITAN_OK; ++ return 0; +} + +/* -+ * Initialize the device as an Ethernet device ++ * sci_int_routine : sci main interrupt routine ++ * we will do the query and get event number together ++ * so the interrupt routine should be longer than 120us ++ * now at least 3ms elpase for it. + */ -+static int __init titan_ge_probe(struct device *device) ++static irqreturn_t sci_int_routine(int irq, void *dev_id) +{ -+ titan_ge_port_info *titan_ge_eth; -+ struct net_device *netdev; -+ int port = to_platform_device(device)->id; -+ int err; ++ int ret; + -+ netdev = alloc_etherdev(sizeof(titan_ge_port_info)); -+ if (!netdev) { -+ err = -ENODEV; -+ goto out; ++ if (sci_device->irq != irq) { ++ PRINTK_DBG(KERN_ERR "EC SCI :spurious irq.\n"); ++ return IRQ_NONE; + } + -+ netdev->open = titan_ge_open; -+ netdev->stop = titan_ge_stop; -+ netdev->hard_start_xmit = titan_ge_start_xmit; -+ netdev->get_stats = titan_ge_get_stats; -+ netdev->set_multicast_list = titan_ge_set_multi; -+ netdev->set_mac_address = titan_ge_set_mac_address; -+ -+ /* Tx timeout */ -+ netdev->tx_timeout = titan_ge_tx_timeout; -+ netdev->watchdog_timeo = 2 * HZ; -+ -+ /* Set these to very high values */ -+ netdev->poll = titan_ge_poll; -+ netdev->weight = 64; -+ -+ netdev->tx_queue_len = TITAN_GE_TX_QUEUE; -+ netif_carrier_off(netdev); -+ netdev->base_addr = 0; -+ -+ netdev->change_mtu = titan_ge_change_mtu; -+ -+ titan_ge_eth = netdev_priv(netdev); -+ /* Allocation of memory for the driver structures */ -+ -+ titan_ge_eth->port_num = port; -+ -+ /* Configure the Tx timeout handler */ -+ INIT_WORK(&titan_ge_eth->tx_timeout_task, -+ (void (*)(void *)) titan_ge_tx_timeout_task, netdev); -+ -+ spin_lock_init(&titan_ge_eth->lock); ++ /* query the event number */ ++ ret = sci_query_event_num(); ++ if (ret < 0) { ++ PRINTK_DBG("ret 1: %d\n", ret); ++ return IRQ_NONE; ++ } + -+ /* set MAC addresses */ -+ memcpy(netdev->dev_addr, titan_ge_mac_addr_base, 6); -+ netdev->dev_addr[5] += port; ++ ret = sci_get_event_num(); ++ if (ret < 0) { ++ PRINTK_DBG("ret 2: %d\n", ret); ++ return IRQ_NONE; ++ } ++ sci_device->sci_number = ret; + -+ err = register_netdev(netdev); ++ PRINTK_DBG(KERN_INFO "sci_number :0x%x\n", sci_device->sci_number); + -+ if (err) -+ goto out_free_netdev; ++ /* parse the event number and wake the queue */ ++ if ((sci_device->sci_number != 0x00) ++ && (sci_device->sci_number != 0xff)) { ++ ret = sci_parse_num(sci_device); ++ PRINTK_DBG("ret 3: %d\n", ret); ++ if (!ret) ++ sci_device->irq_data = 1; ++ else ++ sci_device->irq_data = 0; + -+ printk(KERN_NOTICE -+ "%s: port %d with MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", -+ netdev->name, port, netdev->dev_addr[0], -+ netdev->dev_addr[1], netdev->dev_addr[2], -+ netdev->dev_addr[3], netdev->dev_addr[4], -+ netdev->dev_addr[5]); ++ wake_up_interruptible(&(sci_device->wq)); ++ PRINTK_DBG("interrupitble\n"); ++ } + -+ printk(KERN_NOTICE "Rx NAPI supported, Tx Coalescing ON \n"); ++ return IRQ_HANDLED; ++} + ++static int sci_open(struct inode *inode, struct file *filp) ++{ ++ PRINTK_DBG(KERN_INFO "SCI : open ok.\n"); + return 0; -+ -+out_free_netdev: -+ kfree(netdev); -+ -+out: -+ return err; +} + -+static void __devexit titan_device_remove(struct device *device) ++static int sci_release(struct inode *inode, struct file *filp) +{ ++ PRINTK_DBG(KERN_INFO "SCI : close ok.\n"); ++ return 0; +} + +/* -+ * Reset the Ethernet port ++ * sci_poll : poll routine for upper layer using + */ -+static void titan_ge_port_reset(unsigned int port_num) ++static unsigned int sci_poll(struct file *fp, poll_table * wait) +{ -+ unsigned int reg_data; -+ -+ /* Stop the Tx port activity */ -+ reg_data = TITAN_GE_READ(TITAN_GE_TMAC_CONFIG_1 + -+ (port_num << 12)); -+ reg_data &= ~(0x0001); -+ TITAN_GE_WRITE((TITAN_GE_TMAC_CONFIG_1 + -+ (port_num << 12)), reg_data); ++ int mask = 0; + -+ /* Stop the Rx port activity */ -+ reg_data = TITAN_GE_READ(TITAN_GE_RMAC_CONFIG_1 + -+ (port_num << 12)); -+ reg_data &= ~(0x0001); -+ TITAN_GE_WRITE((TITAN_GE_RMAC_CONFIG_1 + -+ (port_num << 12)), reg_data); ++ /* printk("current task %p\n", current); */ ++ poll_wait(fp, &(sci_device->wq), wait); ++ if (sci_device->irq_data) { ++ /* printk("current task 1 %p\n", current); */ ++ mask = POLLIN | POLLRDNORM; ++ } + -+ return; ++ return mask; +} + -+/* -+ * Return the Tx desc after use by the XDMA -+ */ -+static int titan_ge_return_tx_desc(titan_ge_port_info * titan_ge_eth, int port) ++static int sci_ioctl(struct inode *inode, struct file *filp, unsigned long cmd, ++ unsigned long arg) +{ -+ int tx_desc_used; -+ struct sk_buff *skb; -+ -+ tx_desc_used = titan_ge_eth->tx_used_desc_q; -+ -+ /* return right away */ -+ if (tx_desc_used == titan_ge_eth->tx_curr_desc_q) -+ return TITAN_ERROR; -+ -+ /* Now the critical stuff */ -+ skb = titan_ge_eth->tx_skb[tx_desc_used]; -+ -+ dev_kfree_skb_any(skb); ++ void __user *ptr = (void __user *)arg; ++ int ret = 0; + -+ titan_ge_eth->tx_skb[tx_desc_used] = NULL; -+ titan_ge_eth->tx_used_desc_q = -+ (tx_desc_used + 1) % TITAN_GE_TX_QUEUE; ++ switch (cmd) { ++/* case IOCTL_GET_INIT_STATE : */ ++ case 1: ++ ret = copy_from_user(&ecreg, ptr, sizeof(struct ec_sci_reg)); ++ if (ret) { ++ printk(KERN_ERR "read from user error.\n"); ++ return -EFAULT; ++ } ++ if (ecreg.addr < 0xf400 || ecreg.addr > 0xffff) ++ return -EINVAL; ++ ecreg.val = ec_read(ecreg.addr); ++ ret = copy_to_user(ptr, &ecreg, sizeof(struct ec_sci_reg)); ++ if (ret) { ++ printk(KERN_ERR "reg read : copy to user error.\n"); ++ return -EFAULT; ++ } ++ break; ++ default: ++ break; ++ } + + return 0; +} + -+/* -+ * Coalescing for the Tx path -+ */ -+static unsigned long titan_ge_tx_coal(unsigned long delay, int port) ++static long sci_compat_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) +{ -+ unsigned long rx_delay; -+ -+ rx_delay = TITAN_GE_READ(TITAN_GE_INT_COALESCING); -+ delay = (delay << 16) | rx_delay; ++ return sci_ioctl(file->f_dentry->d_inode, file, cmd, arg); ++} + -+ TITAN_GE_WRITE(TITAN_GE_INT_COALESCING, delay); -+ TITAN_GE_WRITE(0x5038, delay); ++static const struct file_operations sci_fops = { ++#ifdef CONFIG_64BIT ++ .compat_ioctl = sci_compat_ioctl, ++#else ++ .ioclt = sci_ioctl, ++#endif ++ .open = sci_open, ++ .poll = sci_poll, ++ .release = sci_release, ++}; + -+ return delay; -+} ++static struct miscdevice sci_dev = { ++ .minor = EC_SCI_MINOR_DEV, ++ .name = EC_SCI_DEV, ++ .fops = &sci_fops ++}; + -+static struct device_driver titan_soc_driver = { -+ .name = titan_string, -+ .bus = &platform_bus_type, -+ .probe = titan_ge_probe, -+ .remove = __devexit_p(titan_device_remove), ++static struct pci_device_id sci_pci_tbl[] = { ++ {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA)}, ++ {} +}; + -+static void titan_platform_release (struct device *device) ++MODULE_DEVICE_TABLE(pci, sci_pci_tbl); ++ ++/* ++ * sci_low_level_init : ++ * config and init some msr and gpio register properly. ++ */ ++static int sci_low_level_init(struct sci_device *scidev) +{ -+ struct platform_device *pldev; ++ u32 hi, lo; ++ u32 gpio_base = scidev->gpio_base; ++ int ret = 0; ++ unsigned long flags; ++ ++ /* filter the former kb3310 interrupt for security */ ++ ret = sci_query_event_num(); ++ if (ret) { ++ PRINTK_DBG(KERN_ERR ++ "sci low level init query event num failed.\n"); ++ return ret; ++ } ++ ++ /* for filtering next number interrupt */ ++ udelay(10000); ++ ++ /* set gpio native registers and msrs for GPIO27 SCI EVENT PIN ++ * gpio : ++ * input, pull-up, no-invert, event-count and value 0, ++ * no-filter, no edge mode ++ * gpio27 map to Virtual gpio0 ++ * msr : ++ * no primary and lpc ++ * Unrestricted Z input to IG10 from Virtual gpio 0. ++ */ ++ local_irq_save(flags); ++ _rdmsr(0x80000024, &hi, &lo); ++ lo &= ~(1 << 10); ++ _wrmsr(0x80000024, hi, lo); ++ _rdmsr(0x80000025, &hi, &lo); ++ lo &= ~(1 << 10); ++ _wrmsr(0x80000025, hi, lo); ++ _rdmsr(0x80000023, &hi, &lo); ++ lo |= (0x0a << 0); ++ _wrmsr(0x80000023, hi, lo); ++ local_irq_restore(flags); ++ ++ /* set gpio27 as sci interrupt : ++ * input, pull-up, no-fliter, no-negedge, invert ++ * the sci event is just about 120us ++ */ ++ asm(".set noreorder\n"); ++ /* input enable */ ++ outl(0x00000800, (gpio_base | 0xA0)); ++ /* revert the input */ ++ outl(0x00000800, (gpio_base | 0xA4)); ++ /* event-int enable */ ++ outl(0x00000800, (gpio_base | 0xB8)); ++ asm(".set reorder\n"); + -+ /* free device */ -+ pldev = to_platform_device (device); -+ kfree (pldev); ++ return 0; +} + +/* -+ * Register the Titan GE with the kernel ++ * sci_pci_init : ++ * pci init routine + */ -+static int __init titan_ge_init_module(void) ++static int __devinit sci_pci_init(struct pci_dev *pdev, ++ const struct pci_device_id *ent) +{ -+ struct platform_device *pldev; -+ unsigned int version, device; ++ u32 gpio_base; ++ int ret = -EIO; + int i; + -+ printk(KERN_NOTICE -+ "PMC-Sierra TITAN 10/100/1000 Ethernet Driver \n"); -+ -+ titan_ge_base = (unsigned long) ioremap(TITAN_GE_BASE, TITAN_GE_SIZE); -+ if (!titan_ge_base) { -+ printk("Mapping Titan GE failed\n"); -+ goto out; ++ /* init the sci device */ ++ sci_device = kmalloc(sizeof(struct sci_device), GFP_KERNEL); ++ if (sci_device == NULL) { ++ PRINTK_DBG(KERN_ERR ++ "EC SCI : get memory for sci_device failed.\n"); ++ return -ENOMEM; + } -+ -+ device = TITAN_GE_READ(TITAN_GE_DEVICE_ID); -+ version = (device & 0x000f0000) >> 16; -+ device &= 0x0000ffff; -+ -+ printk(KERN_NOTICE "Device Id : %x, Version : %x \n", device, version); -+ -+#ifdef TITAN_RX_RING_IN_SRAM -+ titan_ge_sram = (unsigned long) ioremap(TITAN_SRAM_BASE, -+ TITAN_SRAM_SIZE); -+ if (!titan_ge_sram) { -+ printk("Mapping Titan SRAM failed\n"); -+ goto out_unmap_ge; ++ init_waitqueue_head(&(sci_device->wq)); ++ spin_lock_init(&sci_device->lock); ++ sci_device->irq = SCI_IRQ_NUM; ++ sci_device->irq_data = 0x00; ++ sci_device->sci_number = 0x00; ++ strcpy(sci_device->name, EC_SCI_DEV); ++ ++ sci_device->sci_init_value[0] = ec_read(REG_DISPLAY_BRIGHTNESS); ++ sci_device->sci_init_value[1] = ec_read(REG_AUDIO_VOLUME); ++ ++ for (i = 0; i < SCI_MAX_EVENT_COUNT; i++) ++ sci_device->sci_num_array[i] = 0x00; ++ ++ /* enable pci device and get the GPIO resources */ ++ ret = pci_enable_device(pdev); ++ if (ret) { ++ PRINTK_DBG(KERN_ERR "EC SCI : enable pci device failed.\n"); ++ ret = -ENODEV; ++ goto out_pdev; + } -+#endif + -+ if (driver_register(&titan_soc_driver)) { -+ printk(KERN_ERR "Driver registration failed\n"); -+ goto out_unmap_sram; ++ gpio_base = 0x0000; ++ gpio_base = pci_resource_start(pdev, 1); ++ gpio_base &= ~0x0003; ++ if (gpio_base == 0x0000) { ++ PRINTK_DBG(KERN_ERR "EC SCI : get resource failed.\n"); ++ ret = -ENODEV; ++ goto out_resource; ++ } ++ if (request_region(gpio_base, CS5536_GPIO_SIZE, EC_SCI_DEV) == NULL) { ++ PRINTK_DBG(KERN_ERR ++ "EC SCI : base 0x%x, length 0x%x already in use.\n", ++ gpio_base, CS5536_GPIO_SIZE); ++ goto out_resource; ++ } ++ sci_device->gpio_base = gpio_base; ++ sci_device->gpio_size = CS5536_GPIO_SIZE; ++ ++ /* init the relative gpio and msrs */ ++ ret = sci_low_level_init(sci_device); ++ if (ret < 0) { ++ printk(KERN_ERR "EC SCI : low level init failed.\n"); ++ goto out_irq; + } + -+ for (i = 0; i < 3; i++) { -+ titan_ge_device[i] = NULL; -+ -+ if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) -+ continue; -+ -+ memset (pldev, 0, sizeof (*pldev)); -+ pldev->name = titan_string; -+ pldev->id = i; -+ pldev->dev.release = titan_platform_release; -+ titan_ge_device[i] = pldev; -+ -+ if (platform_device_register (pldev)) { -+ kfree (pldev); -+ titan_ge_device[i] = NULL; -+ continue; -+ } -+ -+ if (!pldev->dev.driver) { -+ /* -+ * The driver was not bound to this device, there was -+ * no hardware at this address. Unregister it, as the -+ * release fuction will take care of freeing the -+ * allocated structure -+ */ -+ titan_ge_device[i] = NULL; -+ platform_device_unregister (pldev); -+ } ++ /* alloc the interrupt for sci not pci */ ++ ret = ++ request_irq(sci_device->irq, sci_int_routine, IRQF_SHARED, ++ sci_device->name, sci_device); ++ if (ret) { ++ printk(KERN_ERR "EC SCI : request irq %d failed.\n", ++ sci_device->irq); ++ ret = -EFAULT; ++ goto out_irq; + } + -+ return 0; ++ /* register the misc device */ ++ ret = misc_register(&sci_dev); ++ if (ret != 0) { ++ printk(KERN_ERR "EC SCI : misc register failed.\n"); ++ ret = -EFAULT; ++ goto out_misc; ++ } + -+out_unmap_sram: -+ iounmap((void *)titan_ge_sram); ++ ret = 0; ++ PRINTK_DBG(KERN_INFO "sci probe ok...\n"); ++ goto out; ++ ++ out_misc: ++ free_irq(sci_device->irq, sci_device); ++ out_irq: ++ release_region(sci_device->gpio_base, sci_device->gpio_size); ++ out_resource: ++ pci_disable_device(pdev); ++ out_pdev: ++ kfree(sci_device); ++ out: ++ return ret; ++} + -+out_unmap_ge: -+ iounmap((void *)titan_ge_base); ++static void __devexit sci_pci_remove(struct pci_dev *pdev) ++{ ++ misc_deregister(&sci_dev); ++ free_irq(sci_device->irq, sci_device); ++ release_region(sci_device->gpio_base, sci_device->gpio_size); ++ pci_disable_device(pdev); ++ kfree(sci_device); + -+out: -+ return -ENOMEM; ++ return; +} + -+/* -+ * Unregister the Titan GE from the kernel -+ */ -+static void __exit titan_ge_cleanup_module(void) ++static struct pci_driver sci_driver = { ++ .name = EC_SCI_DEV, ++ .id_table = sci_pci_tbl, ++ .probe = sci_pci_init, ++ .remove = __devexit_p(sci_pci_remove), ++}; ++ ++static int __init sci_init(void) +{ -+ int i; ++ int ret = 0; + -+ driver_unregister(&titan_soc_driver); ++#ifdef CONFIG_PROC_FS ++ sci_proc_entry = NULL; ++ sci_proc_entry = create_proc_entry(EC_SCI_DEV, S_IWUSR | S_IRUGO, NULL); ++ if (sci_proc_entry == NULL) { ++ printk(KERN_ERR "EC SCI : register /proc/sci failed.\n"); ++ return -EINVAL; ++ } ++ sci_proc_entry->proc_fops = &sci_proc_fops; ++#endif + -+ for (i = 0; i < 3; i++) { -+ if (titan_ge_device[i]) { -+ platform_device_unregister (titan_ge_device[i]); -+ titan_ge_device[i] = NULL; -+ } ++ ret = pci_register_driver(&sci_driver); ++ if (ret) { ++ printk(KERN_ERR "EC SCI : registrer pci driver error.\n"); ++#ifdef CONFIG_PROC_FS ++ remove_proc_entry(EC_SCI_DEV, NULL); ++#endif ++ return ret; + } + -+ iounmap((void *)titan_ge_sram); -+ iounmap((void *)titan_ge_base); -+} ++ printk(KERN_INFO ++ "SCI event handler on KB3310B Embedded Controller init.\n"); + -+MODULE_AUTHOR("Manish Lachwani "); -+MODULE_DESCRIPTION("Titan GE Ethernet driver"); -+MODULE_LICENSE("GPL"); ++ return ret; ++} + -+module_init(titan_ge_init_module); -+module_exit(titan_ge_cleanup_module); -diff -Nur linux-2.6.30.orig/drivers/net/titan_ge.h linux-2.6.30/drivers/net/titan_ge.h ---- linux-2.6.30.orig/drivers/net/titan_ge.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/drivers/net/titan_ge.h 2009-06-14 20:25:20.000000000 +0200 -@@ -0,0 +1,415 @@ -+#ifndef _TITAN_GE_H_ -+#define _TITAN_GE_H_ ++static void __exit sci_exit(void) ++{ ++#ifdef CONFIG_PROC_FS ++ remove_proc_entry(EC_SCI_DEV, NULL); ++#endif ++ pci_unregister_driver(&sci_driver); ++ printk(KERN_INFO ++ "SCI event handler on KB3310B Embedded Controller exit.\n"); + -+#include -+#include -+#include -+#include ++ return; ++} + -+/* -+ * These functions should be later moved to a more generic location since there -+ * will be others accessing it also -+ */ ++module_init(sci_init); ++module_exit(sci_exit); + ++MODULE_AUTHOR("liujl "); ++MODULE_DESCRIPTION("SCI Event Management for KB3310"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/io_msr_debug.c linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/io_msr_debug.c +--- linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/io_msr_debug.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/io_msr_debug.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,198 @@ +/* -+ * This is the way it works: LKB5 Base is at 0x0128. TITAN_BASE is defined in -+ * include/asm/titan_dep.h. TITAN_GE_BASE is the value in the TITAN_GE_LKB5 -+ * register. ++ * Debug IO and MSR resources driver on Linux ++ * ++ * Author: liujl ++ * huangw ++ * Date : 2009-03-03 ++ * ++ * NOTE : ++ * 1, The IO and the MSR resources accessing read/write are supported. + */ + -+#define TITAN_GE_BASE 0xfe000000UL -+#define TITAN_GE_SIZE 0x10000UL ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+extern unsigned long titan_ge_base; ++#include + -+#define TITAN_GE_WRITE(offset, data) \ -+ *(volatile u32 *)(titan_ge_base + (offset)) = (data) ++#include "ec.h" + -+#define TITAN_GE_READ(offset) *(volatile u32 *)(titan_ge_base + (offset)) ++struct io_msr_reg { ++ u32 addr; /* the address of IO and MSR registers */ ++ u8 val; /* the register value for IO */ ++ u32 hi; /* the register value for MSR's high part */ ++ u32 lo; /* the register value for MSR's low part */ ++}; + -+#ifndef msec_delay -+#define msec_delay(x) do { if(in_interrupt()) { \ -+ /* Don't mdelay in interrupt context! */ \ -+ BUG(); \ -+ } else { \ -+ set_current_state(TASK_UNINTERRUPTIBLE); \ -+ schedule_timeout((x * HZ)/1000); \ -+ } } while(0) -+#endif ++#define IOCTL_RDMSR _IOR('F', 5, int) ++#define IOCTL_WRMSR _IOR('F', 6, int) ++#define IOCTL_RDIO _IOR('F', 7, int) ++#define IOCTL_WRIO _IOR('F', 8, int) + -+#define TITAN_GE_PORT_0 ++/* ec io space range */ ++#define IO_MAX_ADDR 0xBFD0FFFF ++#define IO_MIN_ADDR 0xBFD00000 + -+#define TITAN_SRAM_BASE ((OCD_READ(RM9000x2_OCD_LKB13) & ~1) << 4) -+#define TITAN_SRAM_SIZE 0x2000UL ++static int io_msr_ioctl(struct inode *inode, struct file *filp, u_int cmd, ++ u_long arg) ++{ ++ void __user *ptr = (void __user *)arg; ++ struct io_msr_reg *iomsrreg = (struct io_msr_reg *)(filp->private_data); ++ int ret = 0; + -+/* -+ * We may need these constants -+ */ -+#define TITAN_BIT0 0x00000001 -+#define TITAN_BIT1 0x00000002 -+#define TITAN_BIT2 0x00000004 -+#define TITAN_BIT3 0x00000008 -+#define TITAN_BIT4 0x00000010 -+#define TITAN_BIT5 0x00000020 -+#define TITAN_BIT6 0x00000040 -+#define TITAN_BIT7 0x00000080 -+#define TITAN_BIT8 0x00000100 -+#define TITAN_BIT9 0x00000200 -+#define TITAN_BIT10 0x00000400 -+#define TITAN_BIT11 0x00000800 -+#define TITAN_BIT12 0x00001000 -+#define TITAN_BIT13 0x00002000 -+#define TITAN_BIT14 0x00004000 -+#define TITAN_BIT15 0x00008000 -+#define TITAN_BIT16 0x00010000 -+#define TITAN_BIT17 0x00020000 -+#define TITAN_BIT18 0x00040000 -+#define TITAN_BIT19 0x00080000 -+#define TITAN_BIT20 0x00100000 -+#define TITAN_BIT21 0x00200000 -+#define TITAN_BIT22 0x00400000 -+#define TITAN_BIT23 0x00800000 -+#define TITAN_BIT24 0x01000000 -+#define TITAN_BIT25 0x02000000 -+#define TITAN_BIT26 0x04000000 -+#define TITAN_BIT27 0x08000000 -+#define TITAN_BIT28 0x10000000 -+#define TITAN_BIT29 0x20000000 -+#define TITAN_BIT30 0x40000000 -+#define TITAN_BIT31 0x80000000 -+ -+/* Flow Control */ -+#define TITAN_GE_FC_NONE 0x0 -+#define TITAN_GE_FC_FULL 0x1 -+#define TITAN_GE_FC_TX_PAUSE 0x2 -+#define TITAN_GE_FC_RX_PAUSE 0x3 -+ -+/* Duplex Settings */ -+#define TITAN_GE_FULL_DUPLEX 0x1 -+#define TITAN_GE_HALF_DUPLEX 0x2 -+ -+/* Speed settings */ -+#define TITAN_GE_SPEED_1000 0x1 -+#define TITAN_GE_SPEED_100 0x2 -+#define TITAN_GE_SPEED_10 0x3 -+ -+/* Debugging info only */ -+#undef TITAN_DEBUG -+ -+/* Keep the rings in the Titan's SSRAM */ -+#define TITAN_RX_RING_IN_SRAM ++ switch (cmd) { ++ case IOCTL_RDIO: ++ ret = copy_from_user(iomsrreg, ptr, sizeof(struct io_msr_reg)); ++ if (ret) { ++ printk(KERN_ERR "IO read : copy from user error.\n"); ++ return -EFAULT; ++ } + -+#ifdef CONFIG_64BIT -+#define TITAN_GE_IE_MASK 0xfffffffffb001b64 -+#define TITAN_GE_IE_STATUS 0xfffffffffb001b60 ++ if (iomsrreg->addr > IO_MAX_ADDR ++ || iomsrreg->addr < IO_MIN_ADDR) { ++ printk(KERN_ERR "IO read : out of IO address range.\n"); ++ return -EINVAL; ++ } ++#ifdef CONFIG_64BIT ++ iomsrreg->val = ++ *((unsigned char *)(iomsrreg-> ++ addr | 0xffffffff00000000)); +#else -+#define TITAN_GE_IE_MASK 0xfb001b64 -+#define TITAN_GE_IE_STATUS 0xfb001b60 ++ iomsrreg->val = *((unsigned char *)(iomsrreg->addr)); +#endif ++ ret = copy_to_user(ptr, iomsrreg, sizeof(struct io_msr_reg)); ++ if (ret) { ++ printk(KERN_ERR "IO read : copy to user error.\n"); ++ return -EFAULT; ++ } ++ break; ++ case IOCTL_WRIO: ++ ret = copy_from_user(iomsrreg, ptr, sizeof(struct io_msr_reg)); ++ if (ret) { ++ printk(KERN_ERR "IO write : copy from user error.\n"); ++ return -EFAULT; ++ } + -+/* Support for Jumbo Frames */ -+#undef TITAN_GE_JUMBO_FRAMES -+ -+/* Rx buffer size */ -+#ifdef TITAN_GE_JUMBO_FRAMES -+#define TITAN_GE_JUMBO_BUFSIZE 9080 ++ if (iomsrreg->addr > IO_MAX_ADDR ++ || iomsrreg->addr < IO_MIN_ADDR) { ++ printk(KERN_ERR ++ "IO write : out of IO address range.\n"); ++ return -EINVAL; ++ } ++#ifdef CONFIG_64BIT ++ *((unsigned char *)(iomsrreg->addr | 0xffffffff00000000)) = ++ iomsrreg->val; +#else -+#define TITAN_GE_STD_BUFSIZE 1580 ++ *((unsigned char *)(iomsrreg->addr)) = iomsrreg->val; +#endif ++ break; ++ case IOCTL_RDMSR: ++ ret = copy_from_user(iomsrreg, ptr, sizeof(struct io_msr_reg)); ++ if (ret) { ++ printk(KERN_ERR "MSR read : copy from user error.\n"); ++ return -EFAULT; ++ } ++ _rdmsr(iomsrreg->addr, &(iomsrreg->hi), &(iomsrreg->lo)); ++ ret = copy_to_user(ptr, iomsrreg, sizeof(struct io_msr_reg)); ++ if (ret) { ++ printk(KERN_ERR "MSR read : copy to user error.\n"); ++ return -EFAULT; ++ } ++ break; ++ case IOCTL_WRMSR: ++ ret = copy_from_user(iomsrreg, ptr, sizeof(struct io_msr_reg)); ++ if (ret) { ++ printk(KERN_ERR "MSR write : copy from user error.\n"); ++ return -EFAULT; ++ } ++ _wrmsr(iomsrreg->addr, iomsrreg->hi, iomsrreg->lo); ++ break; + -+/* -+ * Tx and Rx Interrupt Coalescing parameter. These values are -+ * for 1 Ghz processor. Rx coalescing can be taken care of -+ * by NAPI. NAPI is adaptive and hence useful. Tx coalescing -+ * is not adaptive. Hence, these values need to be adjusted -+ * based on load, CPU speed etc. -+ */ -+#define TITAN_GE_RX_COAL 150 -+#define TITAN_GE_TX_COAL 300 -+ -+#if defined(__BIG_ENDIAN) -+ -+/* Define the Rx descriptor */ -+typedef struct eth_rx_desc { -+ u32 reserved; /* Unused */ -+ u32 buffer_addr; /* CPU buffer address */ -+ u32 cmd_sts; /* Command and Status */ -+ u32 buffer; /* XDMA buffer address */ -+} titan_ge_rx_desc; -+ -+/* Define the Tx descriptor */ -+typedef struct eth_tx_desc { -+ u16 cmd_sts; /* Command, Status and Buffer count */ -+ u16 buffer_len; /* Length of the buffer */ -+ u32 buffer_addr; /* Physical address of the buffer */ -+} titan_ge_tx_desc; -+ -+#elif defined(__LITTLE_ENDIAN) -+ -+/* Define the Rx descriptor */ -+typedef struct eth_rx_desc { -+ u32 buffer_addr; /* CPU buffer address */ -+ u32 reserved; /* Unused */ -+ u32 buffer; /* XDMA buffer address */ -+ u32 cmd_sts; /* Command and Status */ -+} titan_ge_rx_desc; -+ -+/* Define the Tx descriptor */ -+typedef struct eth_tx_desc { -+ u32 buffer_addr; /* Physical address of the buffer */ -+ u16 buffer_len; /* Length of the buffer */ -+ u16 cmd_sts; /* Command, Status and Buffer count */ -+} titan_ge_tx_desc; -+#endif -+ -+/* Default Tx Queue Size */ -+#define TITAN_GE_TX_QUEUE 128 -+#define TITAN_TX_RING_BYTES (TITAN_GE_TX_QUEUE * sizeof(struct eth_tx_desc)) -+ -+/* Default Rx Queue Size */ -+#define TITAN_GE_RX_QUEUE 64 -+#define TITAN_RX_RING_BYTES (TITAN_GE_RX_QUEUE * sizeof(struct eth_rx_desc)) -+ -+/* Packet Structure */ -+typedef struct _pkt_info { -+ unsigned int len; -+ unsigned int cmd_sts; -+ unsigned int buffer; -+ struct sk_buff *skb; -+ unsigned int checksum; -+} titan_ge_packet; -+ -+ -+#define PHYS_CNT 3 -+ -+/* Titan Port specific data structure */ -+typedef struct _eth_port_ctrl { -+ unsigned int port_num; -+ u8 port_mac_addr[6]; -+ -+ /* Rx descriptor pointers */ -+ int rx_curr_desc_q, rx_used_desc_q; -+ -+ /* Tx descriptor pointers */ -+ int tx_curr_desc_q, tx_used_desc_q; -+ -+ /* Rx descriptor area */ -+ volatile titan_ge_rx_desc *rx_desc_area; -+ unsigned int rx_desc_area_size; -+ struct sk_buff* rx_skb[TITAN_GE_RX_QUEUE]; -+ -+ /* Tx Descriptor area */ -+ volatile titan_ge_tx_desc *tx_desc_area; -+ unsigned int tx_desc_area_size; -+ struct sk_buff* tx_skb[TITAN_GE_TX_QUEUE]; -+ -+ /* Timeout task */ -+ struct work_struct tx_timeout_task; -+ -+ /* DMA structures and handles */ -+ dma_addr_t tx_dma; -+ dma_addr_t rx_dma; -+ dma_addr_t tx_dma_array[TITAN_GE_TX_QUEUE]; -+ -+ /* Device lock */ -+ spinlock_t lock; -+ -+ unsigned int tx_ring_skbs; -+ unsigned int rx_ring_size; -+ unsigned int tx_ring_size; -+ unsigned int rx_ring_skbs; -+ -+ struct net_device_stats stats; -+ -+ /* Tx and Rx coalescing */ -+ unsigned long rx_int_coal; -+ unsigned long tx_int_coal; -+ -+ /* Threshold for replenishing the Rx and Tx rings */ -+ unsigned int tx_threshold; -+ unsigned int rx_threshold; -+ -+ /* NAPI work limit */ -+ unsigned int rx_work_limit; -+} titan_ge_port_info; -+ -+/* Titan specific constants */ -+#define TITAN_ETH_PORT_IRQ 3 -+ -+/* Max Rx buffer */ -+#define TITAN_GE_MAX_RX_BUFFER 65536 -+ -+/* Tx and Rx Error */ -+#define TITAN_GE_ERROR -+ -+/* Rx Descriptor Command and Status */ -+ -+#define TITAN_GE_RX_CRC_ERROR TITAN_BIT27 /* crc error */ -+#define TITAN_GE_RX_OVERFLOW_ERROR TITAN_BIT15 /* overflow */ -+#define TITAN_GE_RX_BUFFER_OWNED TITAN_BIT21 /* buffer ownership */ -+#define TITAN_GE_RX_STP TITAN_BIT31 /* start of packet */ -+#define TITAN_GE_RX_BAM TITAN_BIT30 /* broadcast address match */ -+#define TITAN_GE_RX_PAM TITAN_BIT28 /* physical address match */ -+#define TITAN_GE_RX_LAFM TITAN_BIT29 /* logical address filter match */ -+#define TITAN_GE_RX_VLAN TITAN_BIT26 /* virtual lans */ -+#define TITAN_GE_RX_PERR TITAN_BIT19 /* packet error */ -+#define TITAN_GE_RX_TRUNC TITAN_BIT20 /* packet size greater than 32 buffers */ -+ -+/* Tx Descriptor Command */ -+#define TITAN_GE_TX_BUFFER_OWNED TITAN_BIT5 /* buffer ownership */ -+#define TITAN_GE_TX_ENABLE_INTERRUPT TITAN_BIT15 /* Interrupt Enable */ -+ -+/* Return Status */ -+#define TITAN_OK 0x1 /* Good Status */ -+#define TITAN_ERROR 0x2 /* Error Status */ -+ -+/* MIB specific register offset */ -+#define TITAN_GE_MSTATX_STATS_BASE_LOW 0x0800 /* MSTATX COUNTL[15:0] */ -+#define TITAN_GE_MSTATX_STATS_BASE_MID 0x0804 /* MSTATX COUNTM[15:0] */ -+#define TITAN_GE_MSTATX_STATS_BASE_HI 0x0808 /* MSTATX COUNTH[7:0] */ -+#define TITAN_GE_MSTATX_CONTROL 0x0828 /* MSTATX Control */ -+#define TITAN_GE_MSTATX_VARIABLE_SELECT 0x082C /* MSTATX Variable Select */ -+ -+/* MIB counter offsets, add to the TITAN_GE_MSTATX_STATS_BASE_XXX */ -+#define TITAN_GE_MSTATX_RXFRAMESOK 0x0040 -+#define TITAN_GE_MSTATX_RXOCTETSOK 0x0050 -+#define TITAN_GE_MSTATX_RXFRAMES 0x0060 -+#define TITAN_GE_MSTATX_RXOCTETS 0x0070 -+#define TITAN_GE_MSTATX_RXUNICASTFRAMESOK 0x0080 -+#define TITAN_GE_MSTATX_RXBROADCASTFRAMESOK 0x0090 -+#define TITAN_GE_MSTATX_RXMULTICASTFRAMESOK 0x00A0 -+#define TITAN_GE_MSTATX_RXTAGGEDFRAMESOK 0x00B0 -+#define TITAN_GE_MSTATX_RXMACPAUSECONTROLFRAMESOK 0x00C0 -+#define TITAN_GE_MSTATX_RXMACCONTROLFRAMESOK 0x00D0 -+#define TITAN_GE_MSTATX_RXFCSERROR 0x00E0 -+#define TITAN_GE_MSTATX_RXALIGNMENTERROR 0x00F0 -+#define TITAN_GE_MSTATX_RXSYMBOLERROR 0x0100 -+#define TITAN_GE_MSTATX_RXLAYER1ERROR 0x0110 -+#define TITAN_GE_MSTATX_RXINRANGELENGTHERROR 0x0120 -+#define TITAN_GE_MSTATX_RXLONGLENGTHERROR 0x0130 -+#define TITAN_GE_MSTATX_RXLONGLENGTHCRCERROR 0x0140 -+#define TITAN_GE_MSTATX_RXSHORTLENGTHERROR 0x0150 -+#define TITAN_GE_MSTATX_RXSHORTLLENGTHCRCERROR 0x0160 -+#define TITAN_GE_MSTATX_RXFRAMES64OCTETS 0x0170 -+#define TITAN_GE_MSTATX_RXFRAMES65TO127OCTETS 0x0180 -+#define TITAN_GE_MSTATX_RXFRAMES128TO255OCTETS 0x0190 -+#define TITAN_GE_MSTATX_RXFRAMES256TO511OCTETS 0x01A0 -+#define TITAN_GE_MSTATX_RXFRAMES512TO1023OCTETS 0x01B0 -+#define TITAN_GE_MSTATX_RXFRAMES1024TO1518OCTETS 0x01C0 -+#define TITAN_GE_MSTATX_RXFRAMES1519TOMAXSIZE 0x01D0 -+#define TITAN_GE_MSTATX_RXSTATIONADDRESSFILTERED 0x01E0 -+#define TITAN_GE_MSTATX_RXVARIABLE 0x01F0 -+#define TITAN_GE_MSTATX_GENERICADDRESSFILTERED 0x0200 -+#define TITAN_GE_MSTATX_UNICASTFILTERED 0x0210 -+#define TITAN_GE_MSTATX_MULTICASTFILTERED 0x0220 -+#define TITAN_GE_MSTATX_BROADCASTFILTERED 0x0230 -+#define TITAN_GE_MSTATX_HASHFILTERED 0x0240 -+#define TITAN_GE_MSTATX_TXFRAMESOK 0x0250 -+#define TITAN_GE_MSTATX_TXOCTETSOK 0x0260 -+#define TITAN_GE_MSTATX_TXOCTETS 0x0270 -+#define TITAN_GE_MSTATX_TXTAGGEDFRAMESOK 0x0280 -+#define TITAN_GE_MSTATX_TXMACPAUSECONTROLFRAMESOK 0x0290 -+#define TITAN_GE_MSTATX_TXFCSERROR 0x02A0 -+#define TITAN_GE_MSTATX_TXSHORTLENGTHERROR 0x02B0 -+#define TITAN_GE_MSTATX_TXLONGLENGTHERROR 0x02C0 -+#define TITAN_GE_MSTATX_TXSYSTEMERROR 0x02D0 -+#define TITAN_GE_MSTATX_TXMACERROR 0x02E0 -+#define TITAN_GE_MSTATX_TXCARRIERSENSEERROR 0x02F0 -+#define TITAN_GE_MSTATX_TXSQETESTERROR 0x0300 -+#define TITAN_GE_MSTATX_TXUNICASTFRAMESOK 0x0310 -+#define TITAN_GE_MSTATX_TXBROADCASTFRAMESOK 0x0320 -+#define TITAN_GE_MSTATX_TXMULTICASTFRAMESOK 0x0330 -+#define TITAN_GE_MSTATX_TXUNICASTFRAMESATTEMPTED 0x0340 -+#define TITAN_GE_MSTATX_TXBROADCASTFRAMESATTEMPTED 0x0350 -+#define TITAN_GE_MSTATX_TXMULTICASTFRAMESATTEMPTED 0x0360 -+#define TITAN_GE_MSTATX_TXFRAMES64OCTETS 0x0370 -+#define TITAN_GE_MSTATX_TXFRAMES65TO127OCTETS 0x0380 -+#define TITAN_GE_MSTATX_TXFRAMES128TO255OCTETS 0x0390 -+#define TITAN_GE_MSTATX_TXFRAMES256TO511OCTETS 0x03A0 -+#define TITAN_GE_MSTATX_TXFRAMES512TO1023OCTETS 0x03B0 -+#define TITAN_GE_MSTATX_TXFRAMES1024TO1518OCTETS 0x03C0 -+#define TITAN_GE_MSTATX_TXFRAMES1519TOMAXSIZE 0x03D0 -+#define TITAN_GE_MSTATX_TXVARIABLE 0x03E0 -+#define TITAN_GE_MSTATX_RXSYSTEMERROR 0x03F0 -+#define TITAN_GE_MSTATX_SINGLECOLLISION 0x0400 -+#define TITAN_GE_MSTATX_MULTIPLECOLLISION 0x0410 -+#define TITAN_GE_MSTATX_DEFERREDXMISSIONS 0x0420 -+#define TITAN_GE_MSTATX_LATECOLLISIONS 0x0430 -+#define TITAN_GE_MSTATX_ABORTEDDUETOXSCOLLS 0x0440 -+ -+/* Interrupt specific defines */ -+#define TITAN_GE_DEVICE_ID 0x0000 /* Device ID */ -+#define TITAN_GE_RESET 0x0004 /* Reset reg */ -+#define TITAN_GE_TSB_CTRL_0 0x000C /* TSB Control reg 0 */ -+#define TITAN_GE_TSB_CTRL_1 0x0010 /* TSB Control reg 1 */ -+#define TITAN_GE_INTR_GRP0_STATUS 0x0040 /* General Interrupt Group 0 Status */ -+#define TITAN_GE_INTR_XDMA_CORE_A 0x0048 /* XDMA Channel Interrupt Status, Core A*/ -+#define TITAN_GE_INTR_XDMA_CORE_B 0x004C /* XDMA Channel Interrupt Status, Core B*/ -+#define TITAN_GE_INTR_XDMA_IE 0x0058 /* XDMA Channel Interrupt Enable */ -+#define TITAN_GE_SDQPF_ECC_INTR 0x480C /* SDQPF ECC Interrupt Status */ -+#define TITAN_GE_SDQPF_RXFIFO_CTL 0x4828 /* SDQPF RxFifo Control and Interrupt Enb*/ -+#define TITAN_GE_SDQPF_RXFIFO_INTR 0x482C /* SDQPF RxFifo Interrupt Status */ -+#define TITAN_GE_SDQPF_TXFIFO_CTL 0x4928 /* SDQPF TxFifo Control and Interrupt Enb*/ -+#define TITAN_GE_SDQPF_TXFIFO_INTR 0x492C /* SDQPF TxFifo Interrupt Status */ -+#define TITAN_GE_SDQPF_RXFIFO_0 0x4840 /* SDQPF RxFIFO Enable */ -+#define TITAN_GE_SDQPF_TXFIFO_0 0x4940 /* SDQPF TxFIFO Enable */ -+#define TITAN_GE_XDMA_CONFIG 0x5000 /* XDMA Global Configuration */ -+#define TITAN_GE_XDMA_INTR_SUMMARY 0x5010 /* XDMA Interrupt Summary */ -+#define TITAN_GE_XDMA_BUFADDRPRE 0x5018 /* XDMA Buffer Address Prefix */ -+#define TITAN_GE_XDMA_DESCADDRPRE 0x501C /* XDMA Descriptor Address Prefix */ -+#define TITAN_GE_XDMA_PORTWEIGHT 0x502C /* XDMA Port Weight Configuration */ -+ -+/* Rx MAC defines */ -+#define TITAN_GE_RMAC_CONFIG_1 0x1200 /* RMAC Configuration 1 */ -+#define TITAN_GE_RMAC_CONFIG_2 0x1204 /* RMAC Configuration 2 */ -+#define TITAN_GE_RMAC_MAX_FRAME_LEN 0x1208 /* RMAC Max Frame Length */ -+#define TITAN_GE_RMAC_STATION_HI 0x120C /* Rx Station Address High */ -+#define TITAN_GE_RMAC_STATION_MID 0x1210 /* Rx Station Address Middle */ -+#define TITAN_GE_RMAC_STATION_LOW 0x1214 /* Rx Station Address Low */ -+#define TITAN_GE_RMAC_LINK_CONFIG 0x1218 /* RMAC Link Configuration */ -+ -+/* Tx MAC defines */ -+#define TITAN_GE_TMAC_CONFIG_1 0x1240 /* TMAC Configuration 1 */ -+#define TITAN_GE_TMAC_CONFIG_2 0x1244 /* TMAC Configuration 2 */ -+#define TITAN_GE_TMAC_IPG 0x1248 /* TMAC Inter-Packet Gap */ -+#define TITAN_GE_TMAC_STATION_HI 0x124C /* Tx Station Address High */ -+#define TITAN_GE_TMAC_STATION_MID 0x1250 /* Tx Station Address Middle */ -+#define TITAN_GE_TMAC_STATION_LOW 0x1254 /* Tx Station Address Low */ -+#define TITAN_GE_TMAC_MAX_FRAME_LEN 0x1258 /* TMAC Max Frame Length */ -+#define TITAN_GE_TMAC_MIN_FRAME_LEN 0x125C /* TMAC Min Frame Length */ -+#define TITAN_GE_TMAC_PAUSE_FRAME_TIME 0x1260 /* TMAC Pause Frame Time */ -+#define TITAN_GE_TMAC_PAUSE_FRAME_INTERVAL 0x1264 /* TMAC Pause Frame Interval */ -+ -+/* GMII register */ -+#define TITAN_GE_GMII_INTERRUPT_STATUS 0x1348 /* GMII Interrupt Status */ -+#define TITAN_GE_GMII_CONFIG_GENERAL 0x134C /* GMII Configuration General */ -+#define TITAN_GE_GMII_CONFIG_MODE 0x1350 /* GMII Configuration Mode */ -+ -+/* Tx and Rx XDMA defines */ -+#define TITAN_GE_INT_COALESCING 0x5030 /* Interrupt Coalescing */ -+#define TITAN_GE_CHANNEL0_CONFIG 0x5040 /* Channel 0 XDMA config */ -+#define TITAN_GE_CHANNEL0_INTERRUPT 0x504c /* Channel 0 Interrupt Status */ -+#define TITAN_GE_GDI_INTERRUPT_ENABLE 0x5050 /* IE for the GDI Errors */ -+#define TITAN_GE_CHANNEL0_PACKET 0x5060 /* Channel 0 Packet count */ -+#define TITAN_GE_CHANNEL0_BYTE 0x5064 /* Channel 0 Byte count */ -+#define TITAN_GE_CHANNEL0_TX_DESC 0x5054 /* Channel 0 Tx first desc */ -+#define TITAN_GE_CHANNEL0_RX_DESC 0x5058 /* Channel 0 Rx first desc */ -+ -+/* AFX (Address Filter Exact) register offsets for Slice 0 */ -+#define TITAN_GE_AFX_EXACT_MATCH_LOW 0x1100 /* AFX Exact Match Address Low*/ -+#define TITAN_GE_AFX_EXACT_MATCH_MID 0x1104 /* AFX Exact Match Address Mid*/ -+#define TITAN_GE_AFX_EXACT_MATCH_HIGH 0x1108 /* AFX Exact Match Address Hi */ -+#define TITAN_GE_AFX_EXACT_MATCH_VID 0x110C /* AFX Exact Match VID */ -+#define TITAN_GE_AFX_MULTICAST_HASH_LOW 0x1110 /* AFX Multicast HASH Low */ -+#define TITAN_GE_AFX_MULTICAST_HASH_MIDLOW 0x1114 /* AFX Multicast HASH MidLow */ -+#define TITAN_GE_AFX_MULTICAST_HASH_MIDHI 0x1118 /* AFX Multicast HASH MidHi */ -+#define TITAN_GE_AFX_MULTICAST_HASH_HI 0x111C /* AFX Multicast HASH Hi */ -+#define TITAN_GE_AFX_ADDRS_FILTER_CTRL_0 0x1120 /* AFX Address Filter Ctrl 0 */ -+#define TITAN_GE_AFX_ADDRS_FILTER_CTRL_1 0x1124 /* AFX Address Filter Ctrl 1 */ -+#define TITAN_GE_AFX_ADDRS_FILTER_CTRL_2 0x1128 /* AFX Address Filter Ctrl 2 */ -+ -+/* Traffic Groomer block */ -+#define TITAN_GE_TRTG_CONFIG 0x1000 /* TRTG Config */ -+ -+#endif /* _TITAN_GE_H_ */ -+ -diff -Nur linux-2.6.30.orig/drivers/net/titan_mdio.c linux-2.6.30/drivers/net/titan_mdio.c ---- linux-2.6.30.orig/drivers/net/titan_mdio.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/drivers/net/titan_mdio.c 2009-06-14 20:25:20.000000000 +0200 -@@ -0,0 +1,217 @@ -+/* -+ * drivers/net/titan_mdio.c - Driver for Titan ethernet ports -+ * -+ * Copyright (C) 2003 PMC-Sierra Inc. -+ * Author : Manish Lachwani (lachwani@pmc-sierra.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Management Data IO (MDIO) driver for the Titan GMII. Interacts with the Marvel PHY -+ * on the Titan. No support for the TBI as yet. -+ * -+ */ ++ default: ++ break; ++ } + -+#include "titan_mdio.h" ++ return 0; ++} + -+#define MDIO_DEBUG ++static long io_msr_compat_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ return io_msr_ioctl(file->f_dentry->d_inode, file, cmd, arg); ++} + -+/* -+ * Local constants -+ */ -+#define MAX_CLKA 1023 -+#define MAX_PHY_DEV 31 -+#define MAX_PHY_REG 31 -+#define WRITEADDRS_OPCODE 0x0 -+#define READ_OPCODE 0x2 -+#define WRITE_OPCODE 0x1 -+#define MAX_MDIO_POLL 100 ++static int io_msr_open(struct inode *inode, struct file *filp) ++{ ++ struct io_msr_reg *iomsrreg = NULL; ++ iomsrreg = kmalloc(sizeof(struct io_msr_reg), GFP_KERNEL); ++ if (iomsrreg) ++ filp->private_data = iomsrreg; + -+/* -+ * Titan MDIO and SCMB registers -+ */ -+#define TITAN_GE_SCMB_CONTROL 0x01c0 /* SCMB Control */ -+#define TITAN_GE_SCMB_CLKA 0x01c4 /* SCMB Clock A */ -+#define TITAN_GE_MDIO_COMMAND 0x01d0 /* MDIO Command */ -+#define TITAN_GE_MDIO_DEVICE_PORT_ADDRESS 0x01d4 /* MDIO Device and Port addrs */ -+#define TITAN_GE_MDIO_DATA 0x01d8 /* MDIO Data */ -+#define TITAN_GE_MDIO_INTERRUPTS 0x01dC /* MDIO Interrupts */ ++ return iomsrreg ? 0 : -ENOMEM; ++} + -+/* -+ * Function to poll the MDIO -+ */ -+static int titan_ge_mdio_poll(void) ++static int io_msr_release(struct inode *inode, struct file *filp) +{ -+ int i, val; ++ struct io_msr_reg *iomsrreg = (struct io_msr_reg *)(filp->private_data); + -+ for (i = 0; i < MAX_MDIO_POLL; i++) { -+ val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND); ++ filp->private_data = NULL; ++ kfree(iomsrreg); + -+ if (!(val & 0x8000)) -+ return TITAN_GE_MDIO_GOOD; -+ } -+ -+ return TITAN_GE_MDIO_ERROR; ++ return 0; +} + ++static const struct file_operations io_msr_fops = { ++ .open = io_msr_open, ++ .release = io_msr_release, ++ .read = NULL, ++ .write = NULL, ++#ifdef CONFIG_64BIT ++ .compat_ioctl = io_msr_compat_ioctl, ++#else ++ .ioctl = io_msr_ioctl, ++#endif ++}; + -+/* -+ * Initialize and configure the MDIO -+ */ -+int titan_ge_mdio_setup(titan_ge_mdio_config *titan_mdio) -+{ -+ unsigned long val; -+ -+ /* Reset the SCMB and program into MDIO mode*/ -+ TITAN_GE_MDIO_WRITE(TITAN_GE_SCMB_CONTROL, 0x9000); -+ TITAN_GE_MDIO_WRITE(TITAN_GE_SCMB_CONTROL, 0x1000); -+ -+ /* CLK A */ -+ val = TITAN_GE_MDIO_READ(TITAN_GE_SCMB_CLKA); -+ val = ( (val & ~(0x03ff)) | (titan_mdio->clka & 0x03ff)); -+ TITAN_GE_MDIO_WRITE(TITAN_GE_SCMB_CLKA, val); ++static struct miscdevice io_msr_device = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = "io_msr_dev", ++ .fops = &io_msr_fops ++}; + -+ /* Preamble Suppresion */ -+ val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND); -+ val = ( (val & ~(0x0001)) | (titan_mdio->mdio_spre & 0x0001)); -+ TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_COMMAND, val); ++static int __init io_msr_init(void) ++{ ++ int ret; + -+ /* MDIO mode */ -+ val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS); -+ val = ( (val & ~(0x4000)) | (titan_mdio->mdio_mode & 0x4000)); -+ TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS, val); ++ printk(KERN_INFO "IO and MSR read/write device init.\n"); ++ ret = misc_register(&io_msr_device); + -+ return TITAN_GE_MDIO_GOOD; ++ return ret; +} + -+/* -+ * Set the PHY address in indirect mode -+ */ -+int titan_ge_mdio_inaddrs(int dev_addr, int reg_addr) ++static void __exit io_msr_exit(void) +{ -+ volatile unsigned long val; -+ -+ /* Setup the PHY device */ -+ val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS); -+ val = ( (val & ~(0x1f00)) | ( (dev_addr << 8) & 0x1f00)); -+ val = ( (val & ~(0x001f)) | ( reg_addr & 0x001f)); -+ TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS, val); ++ printk(KERN_INFO "IO and MSR read/write device exit.\n"); ++ misc_deregister(&io_msr_device); ++} + -+ /* Write the new address */ -+ val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND); -+ val = ( (val & ~(0x0300)) | ( (WRITEADDRS_OPCODE << 8) & 0x0300)); -+ TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_COMMAND, val); ++module_init(io_msr_init); ++module_exit(io_msr_exit); + -+ return TITAN_GE_MDIO_GOOD; -+} ++MODULE_AUTHOR("liujl "); ++MODULE_DESCRIPTION("IO and MSR resources debug"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/Makefile linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/Makefile +--- linux-2.6.30.5.orig/drivers/platform/loongson/ec_kb3310b/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/platform/loongson/ec_kb3310b/Makefile 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,14 @@ ++# ++# Embedded Controller(kb3310b) Driver for Yeeloong laptop ++# + -+/* -+ * Read the MDIO register. This is what the individual parametes mean: -+ * -+ * dev_addr : PHY ID -+ * reg_addr : register offset -+ * -+ * See the spec for the Titan MAC. We operate in the Direct Mode. -+ */ ++obj-$(CONFIG_EC_KB3310B) += ec_miscd.o ec_batd.o ec_ftd.o ec_scid.o + -+#define MAX_RETRIES 2 ++ec_miscd-objs := ec_misc.o ++ec_batd-objs := ec_bat.o ++ec_ftd-objs := ec_ft.o ++ec_scid-objs := ec_sci.o + -+int titan_ge_mdio_read(int dev_addr, int reg_addr, unsigned int *pdata) -+{ -+ volatile unsigned long val; -+ int retries = 0; ++obj-$(CONFIG_EC_KB3310B_DEBUG) += io_msr_debugd.o + -+ /* Setup the PHY device */ ++io_msr_debugd-objs := io_msr_debug.o +diff -Nur linux-2.6.30.5.orig/drivers/platform/loongson/Kconfig linux-2.6.30.5/drivers/platform/loongson/Kconfig +--- linux-2.6.30.5.orig/drivers/platform/loongson/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/platform/loongson/Kconfig 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,68 @@ ++# ++# Loongson Platform Specific Drivers ++# + -+again: -+ val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS); -+ val = ( (val & ~(0x1f00)) | ( (dev_addr << 8) & 0x1f00)); -+ val = ( (val & ~(0x001f)) | ( reg_addr & 0x001f)); -+ val |= 0x4000; -+ TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS, val); ++menuconfig LOONGSON_PLATFORM_DEVICES ++ bool "Loongson Platform Specific Device Drivers" ++ default y ++ ---help--- ++ Say Y here to get to see options for device drivers for various ++ loongson platforms, including vendor-specific laptop extension drivers. ++ This option alone does not add any kernel code. + -+ udelay(30); ++ If you say N, all options in this submenu will be skipped and disabled. + -+ /* Issue the read command */ -+ val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND); -+ val = ( (val & ~(0x0300)) | ( (READ_OPCODE << 8) & 0x0300)); -+ TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_COMMAND, val); ++if LOONGSON_PLATFORM_DEVICES + -+ udelay(30); ++config EC_KB3310B ++ tristate "Embedded Controller: Kb3310b support" ++ depends on LEMOTE_YEELOONG2F ++ default y ++ ---help--- ++ This is a driver for yeeloong laptops. It adds the kb3310b support: ++ i.e. battery management, fan & temperature mangement, sci event ++ management and ec rom flushing. + -+ if (titan_ge_mdio_poll() != TITAN_GE_MDIO_GOOD) -+ return TITAN_GE_MDIO_ERROR; ++ This driver is orignally written by Liu junliang ++ and maintained by huangwei currently. + -+ *pdata = (unsigned int)TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DATA); -+ val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_INTERRUPTS); ++ The original git repository is: http://dev.lemote.com/code/ec_module + -+ udelay(30); ++config EC_KB3310B_DEBUG ++ tristate "Embedded Controller: Kb3310b debug support" ++ depends on EC_KB3310B ++ default n ++ ---help--- ++ This is a driver for yeeloong laptops. It adds the kb3310b debug ++ support. + -+ if (val & 0x2) { -+ if (retries == MAX_RETRIES) -+ return TITAN_GE_MDIO_ERROR; -+ else { -+ retries++; -+ goto again; -+ } -+ } ++ This driver is orignally written by Liu junliang ++ and maintained by huangwei currently. + -+ return TITAN_GE_MDIO_GOOD; -+} ++ The original git repository is: http://dev.lemote.com/code/ec_module + -+/* -+ * Write to the MDIO register -+ * -+ * dev_addr : PHY ID -+ * reg_addr : register that needs to be written to -+ * -+ */ -+int titan_ge_mdio_write(int dev_addr, int reg_addr, unsigned int data) -+{ -+ volatile unsigned long val; ++config PMON_FLASH ++ tristate "MTD map driver for flushing PMON in Linux" ++ depends on MTD && MTD_PARTITIONS ++ default y ++ ---help--- ++ This is a driver for flushing the bootloader(pmon) of ++ fuloong2e,fuloong2f,yeeloong2f in Linux. + -+ if (titan_ge_mdio_poll() != TITAN_GE_MDIO_GOOD) -+ return TITAN_GE_MDIO_ERROR; ++ Here is a basic usage: + -+ /* Setup the PHY device */ -+ val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS); -+ val = ( (val & ~(0x1f00)) | ( (dev_addr << 8) & 0x1f00)); -+ val = ( (val & ~(0x001f)) | ( reg_addr & 0x001f)); -+ val |= 0x4000; -+ TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS, val); ++ 1. load necessary modules + -+ udelay(30); ++ $ modprobe mtd ++ $ modprobe mtdblock ++ $ modprobe pmon_flashd + -+ /* Setup the data to write */ -+ TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DATA, data); ++ 2. read the flash + -+ udelay(30); ++ $ dd if=/dev/mtdblock0 of=pmon.bin + -+ /* Issue the write command */ -+ val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND); -+ val = ( (val & ~(0x0300)) | ( (WRITE_OPCODE << 8) & 0x0300)); -+ TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_COMMAND, val); ++ 3. write the falsh + -+ udelay(30); ++ $ dd if=pmon.bin of=/dev/mtdblock0 + -+ if (titan_ge_mdio_poll() != TITAN_GE_MDIO_GOOD) -+ return TITAN_GE_MDIO_ERROR; ++endif # LOONGSON_PLATFORM_DEVICES +diff -Nur linux-2.6.30.5.orig/drivers/platform/loongson/Makefile linux-2.6.30.5/drivers/platform/loongson/Makefile +--- linux-2.6.30.5.orig/drivers/platform/loongson/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/platform/loongson/Makefile 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,6 @@ ++# ++# loongson platform specific drivers ++# + -+ val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_INTERRUPTS); -+ if (val & 0x2) -+ return TITAN_GE_MDIO_ERROR; ++obj-$(CONFIG_EC_KB3310B) += ec_kb3310b/ ++obj-$(CONFIG_PMON_FLASH) += pmon_flash/ +diff -Nur linux-2.6.30.5.orig/drivers/platform/loongson/pmon_flash/Makefile linux-2.6.30.5/drivers/platform/loongson/pmon_flash/Makefile +--- linux-2.6.30.5.orig/drivers/platform/loongson/pmon_flash/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/platform/loongson/pmon_flash/Makefile 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,7 @@ ++# ++# MTD map driver for flushing pmon flash ++# + -+ return TITAN_GE_MDIO_GOOD; -+} ++obj-$(CONFIG_PMON_FLASH) += pmon_flashd.o + -diff -Nur linux-2.6.30.orig/drivers/net/titan_mdio.h linux-2.6.30/drivers/net/titan_mdio.h ---- linux-2.6.30.orig/drivers/net/titan_mdio.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/drivers/net/titan_mdio.h 2009-06-14 20:25:20.000000000 +0200 -@@ -0,0 +1,56 @@ ++pmon_flashd-objs := pmon_flash.o +diff -Nur linux-2.6.30.5.orig/drivers/platform/loongson/pmon_flash/pmon_flash.c linux-2.6.30.5/drivers/platform/loongson/pmon_flash/pmon_flash.c +--- linux-2.6.30.5.orig/drivers/platform/loongson/pmon_flash/pmon_flash.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/platform/loongson/pmon_flash/pmon_flash.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,85 @@ +/* -+ * MDIO used to interact with the PHY when using GMII/MII ++ * Copyright www.lemote.com ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. + */ -+#ifndef _TITAN_MDIO_H -+#define _TITAN_MDIO_H + -+#include -+#include -+#include -+#include "titan_ge.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define FLASH_PHYS_ADDR 0x1fc00000 ++#define FLASH_SIZE 0x080000 ++ ++#define FLASH_PARTITION0_ADDR 0x00000000 ++#define FLASH_PARTITION0_SIZE 0x00080000 ++ ++struct map_info flash_map = { ++ .name = "flash device", ++ .size = FLASH_SIZE, ++ .bankwidth = 1, ++}; + ++struct mtd_partition flash_parts[] = { ++ { ++ .name = "Bootloader", ++ .offset = FLASH_PARTITION0_ADDR, ++ .size = FLASH_PARTITION0_SIZE}, ++}; + -+#define TITAN_GE_MDIO_ERROR (-9000) -+#define TITAN_GE_MDIO_GOOD 0 ++#define PARTITION_COUNT ARRAY_SIZE(flash_parts) + -+#define TITAN_GE_MDIO_BASE titan_ge_base ++static struct mtd_info *mymtd; + -+#define TITAN_GE_MDIO_READ(offset) \ -+ *(volatile u32 *)(titan_ge_base + (offset)) ++int __init init_flash(void) ++{ ++ printk(KERN_NOTICE "Flash flash device: %x at %x\n", ++ FLASH_SIZE, FLASH_PHYS_ADDR); + -+#define TITAN_GE_MDIO_WRITE(offset, data) \ -+ *(volatile u32 *)(titan_ge_base + (offset)) = (data) ++ flash_map.phys = FLASH_PHYS_ADDR; ++ flash_map.virt = ioremap(FLASH_PHYS_ADDR, FLASH_SIZE); + ++ if (!flash_map.virt) { ++ printk(KERN_NOTICE "Failed to ioremap\n"); ++ return -EIO; ++ } + -+/* GMII specific registers */ -+#define TITAN_GE_MARVEL_PHY_ID 0x00 -+#define TITAN_PHY_AUTONEG_ADV 0x04 -+#define TITAN_PHY_LP_ABILITY 0x05 -+#define TITAN_GE_MDIO_MII_CTRL 0x09 -+#define TITAN_GE_MDIO_MII_EXTENDED 0x0f -+#define TITAN_GE_MDIO_PHY_CTRL 0x10 -+#define TITAN_GE_MDIO_PHY_STATUS 0x11 -+#define TITAN_GE_MDIO_PHY_IE 0x12 -+#define TITAN_GE_MDIO_PHY_IS 0x13 -+#define TITAN_GE_MDIO_PHY_LED 0x18 -+#define TITAN_GE_MDIO_PHY_LED_OVER 0x19 -+#define PHY_ANEG_TIME_WAIT 45 /* 45 seconds wait time */ ++ simple_map_init(&flash_map); + -+/* -+ * MDIO Config Structure -+ */ -+typedef struct { -+ unsigned int clka; -+ int mdio_spre; -+ int mdio_mode; -+} titan_ge_mdio_config; ++ mymtd = do_map_probe("cfi_probe", &flash_map); ++ if (mymtd) { ++ add_mtd_partitions(mymtd, flash_parts, PARTITION_COUNT); ++ printk(KERN_NOTICE "pmon flash device initialized\n"); ++ return 0; ++ } + -+/* -+ * Function Prototypes -+ */ -+int titan_ge_mdio_setup(titan_ge_mdio_config *); -+int titan_ge_mdio_inaddrs(int, int); -+int titan_ge_mdio_read(int, int, unsigned int *); -+int titan_ge_mdio_write(int, int, unsigned int); -+ -+#endif /* _TITAN_MDIO_H */ -diff -Nur linux-2.6.30.orig/drivers/rtc/rtc-cmos.c linux-2.6.30/drivers/rtc/rtc-cmos.c ---- linux-2.6.30.orig/drivers/rtc/rtc-cmos.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/drivers/rtc/rtc-cmos.c 2009-06-14 20:25:20.000000000 +0200 ++ iounmap((void *)flash_map.virt); ++ return -ENXIO; ++} ++ ++static void __exit cleanup_flash(void) ++{ ++ if (mymtd) { ++ del_mtd_partitions(mymtd); ++ map_destroy(mymtd); ++ } ++ if (flash_map.virt) { ++ iounmap((void *)flash_map.virt); ++ flash_map.virt = 0; ++ } ++} ++ ++module_init(init_flash); ++module_exit(cleanup_flash); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Yanhua"); ++MODULE_DESCRIPTION("MTD map driver for pmon programming module"); +diff -Nur linux-2.6.30.5.orig/drivers/platform/Makefile linux-2.6.30.5/drivers/platform/Makefile +--- linux-2.6.30.5.orig/drivers/platform/Makefile 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/drivers/platform/Makefile 2009-08-21 21:18:15.000000000 +0200 +@@ -3,3 +3,4 @@ + # + + obj-$(CONFIG_X86) += x86/ ++obj-$(CONFIG_MACH_LOONGSON) += loongson/ +diff -Nur linux-2.6.30.5.orig/drivers/rtc/rtc-cmos.c linux-2.6.30.5/drivers/rtc/rtc-cmos.c +--- linux-2.6.30.5.orig/drivers/rtc/rtc-cmos.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/drivers/rtc/rtc-cmos.c 2009-08-21 21:18:15.000000000 +0200 @@ -691,7 +691,8 @@ */ #if defined(CONFIG_ATARI) @@ -21405,9 +54346,9 @@ diff -Nur linux-2.6.30.orig/drivers/rtc/rtc-cmos.c linux-2.6.30/drivers/rtc/rtc- retval = -ENXIO; goto cleanup1; } -diff -Nur linux-2.6.30.orig/drivers/video/Kconfig linux-2.6.30/drivers/video/Kconfig ---- linux-2.6.30.orig/drivers/video/Kconfig 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/drivers/video/Kconfig 2009-06-14 20:25:20.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/drivers/video/Kconfig linux-2.6.30.5/drivers/video/Kconfig +--- linux-2.6.30.5.orig/drivers/video/Kconfig 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/drivers/video/Kconfig 2009-08-21 21:18:15.000000000 +0200 @@ -1930,6 +1930,28 @@ Turn on debugging messages. Note that you can set/unset at run time through sysfs @@ -21437,9 +54378,9 @@ diff -Nur linux-2.6.30.orig/drivers/video/Kconfig linux-2.6.30/drivers/video/Kco config FB_SM501 tristate "Silicon Motion SM501 framebuffer support" depends on FB && MFD_SM501 -diff -Nur linux-2.6.30.orig/drivers/video/Makefile linux-2.6.30/drivers/video/Makefile ---- linux-2.6.30.orig/drivers/video/Makefile 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/drivers/video/Makefile 2009-06-14 20:25:20.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/drivers/video/Makefile linux-2.6.30.5/drivers/video/Makefile +--- linux-2.6.30.5.orig/drivers/video/Makefile 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/drivers/video/Makefile 2009-08-21 21:18:15.000000000 +0200 @@ -70,6 +70,7 @@ obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o @@ -21448,16 +54389,16 @@ diff -Nur linux-2.6.30.orig/drivers/video/Makefile linux-2.6.30/drivers/video/Ma obj-$(CONFIG_FB_ACORN) += acornfb.o obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \ atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o -diff -Nur linux-2.6.30.orig/drivers/video/sm7xx/Makefile linux-2.6.30/drivers/video/sm7xx/Makefile ---- linux-2.6.30.orig/drivers/video/sm7xx/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/drivers/video/sm7xx/Makefile 2009-06-14 20:25:20.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/drivers/video/sm7xx/Makefile linux-2.6.30.5/drivers/video/sm7xx/Makefile +--- linux-2.6.30.5.orig/drivers/video/sm7xx/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/video/sm7xx/Makefile 2009-08-21 21:18:15.000000000 +0200 @@ -0,0 +1,3 @@ +obj-$(CONFIG_FB_SM7XX) += sm7xx.o + +sm7xx-y := smtcfb.o -diff -Nur linux-2.6.30.orig/drivers/video/sm7xx/smtc2d.c linux-2.6.30/drivers/video/sm7xx/smtc2d.c ---- linux-2.6.30.orig/drivers/video/sm7xx/smtc2d.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/drivers/video/sm7xx/smtc2d.c 2009-06-14 20:25:20.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/drivers/video/sm7xx/smtc2d.c linux-2.6.30.5/drivers/video/sm7xx/smtc2d.c +--- linux-2.6.30.5.orig/drivers/video/sm7xx/smtc2d.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/video/sm7xx/smtc2d.c 2009-08-21 21:18:15.000000000 +0200 @@ -0,0 +1,979 @@ +/* + * smtc2d.c -- Silicon Motion SM7xx 2D drawing engine functions. @@ -22438,9 +55379,9 @@ diff -Nur linux-2.6.30.orig/drivers/video/sm7xx/smtc2d.c linux-2.6.30/drivers/vi + + return de_ctrl; +} -diff -Nur linux-2.6.30.orig/drivers/video/sm7xx/smtc2d.h linux-2.6.30/drivers/video/sm7xx/smtc2d.h ---- linux-2.6.30.orig/drivers/video/sm7xx/smtc2d.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/drivers/video/sm7xx/smtc2d.h 2009-06-14 20:25:20.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/drivers/video/sm7xx/smtc2d.h linux-2.6.30.5/drivers/video/sm7xx/smtc2d.h +--- linux-2.6.30.5.orig/drivers/video/sm7xx/smtc2d.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/video/sm7xx/smtc2d.h 2009-08-21 21:18:15.000000000 +0200 @@ -0,0 +1,530 @@ +/* + * smtc2d.h -- Silicon Motion SM7xx 2D drawing engine functions. @@ -22972,10 +55913,10 @@ diff -Nur linux-2.6.30.orig/drivers/video/sm7xx/smtc2d.h linux-2.6.30/drivers/vi + +extern unsigned long deGetTransparency(void); +extern void deSetPixelFormat(unsigned long bpp); -diff -Nur linux-2.6.30.orig/drivers/video/sm7xx/smtcfb.c linux-2.6.30/drivers/video/sm7xx/smtcfb.c ---- linux-2.6.30.orig/drivers/video/sm7xx/smtcfb.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/drivers/video/sm7xx/smtcfb.c 2009-06-14 20:25:20.000000000 +0200 -@@ -0,0 +1,1135 @@ +diff -Nur linux-2.6.30.5.orig/drivers/video/sm7xx/smtcfb.c linux-2.6.30.5/drivers/video/sm7xx/smtcfb.c +--- linux-2.6.30.5.orig/drivers/video/sm7xx/smtcfb.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/video/sm7xx/smtcfb.c 2009-08-21 21:18:15.000000000 +0200 +@@ -0,0 +1,1138 @@ +/* + * smtcfb.c -- Silicon Motion SM7xx frame buffer device + * @@ -24000,6 +56941,9 @@ diff -Nur linux-2.6.30.orig/drivers/video/sm7xx/smtcfb.c linux-2.6.30/drivers/vi + hw.BaseAddressInVRAM = 0; + sfb->fb.par = &hw; + ++ mutex_init(&sfb->fb.lock); ++ mutex_init(&sfb->fb.mm_lock); ++ + err = register_framebuffer(&sfb->fb); + if (err < 0) + goto failed; @@ -24111,9 +57055,9 @@ diff -Nur linux-2.6.30.orig/drivers/video/sm7xx/smtcfb.c linux-2.6.30/drivers/vi +MODULE_AUTHOR("Siliconmotion "); +MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards"); +MODULE_LICENSE("GPL"); -diff -Nur linux-2.6.30.orig/drivers/video/sm7xx/smtcfb.h linux-2.6.30/drivers/video/sm7xx/smtcfb.h ---- linux-2.6.30.orig/drivers/video/sm7xx/smtcfb.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.30/drivers/video/sm7xx/smtcfb.h 2009-06-14 20:25:20.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/drivers/video/sm7xx/smtcfb.h linux-2.6.30.5/drivers/video/sm7xx/smtcfb.h +--- linux-2.6.30.5.orig/drivers/video/sm7xx/smtcfb.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.30.5/drivers/video/sm7xx/smtcfb.h 2009-08-21 21:18:15.000000000 +0200 @@ -0,0 +1,793 @@ +/* + * smtcfb.h -- Silicon Motion SM7xx frame buffer device @@ -24908,204 +57852,20 @@ diff -Nur linux-2.6.30.orig/drivers/video/sm7xx/smtcfb.h linux-2.6.30/drivers/vi +}; + +#define numVGAModes (sizeof(VGAMode) / sizeof(struct ModeInit)) -diff -Nur linux-2.6.30.orig/fs/autofs4/waitq.c linux-2.6.30/fs/autofs4/waitq.c ---- linux-2.6.30.orig/fs/autofs4/waitq.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/fs/autofs4/waitq.c 2009-06-14 20:25:20.000000000 +0200 -@@ -297,14 +297,20 @@ - */ - if (notify == NFY_MOUNT) { - /* -- * If the dentry was successfully mounted while we slept -- * on the wait queue mutex we can return success. If it -- * isn't mounted (doesn't have submounts for the case of -- * a multi-mount with no mount at it's base) we can -- * continue on and create a new request. -- */ -- if (have_submounts(dentry)) -- return 0; -+ * If the dentry isn't hashed just go ahead and try the -+ * mount again with a new wait (not much else we can do). -+ */ -+ if (!d_unhashed(dentry)) { -+ /* -+ * But if the dentry is hashed, that means that we -+ * got here through the revalidate path. Thus, we -+ * need to check if the dentry has been mounted -+ * while we waited on the wq_mutex. If it has, -+ * simply return success. -+ */ -+ if (d_mountpoint(dentry)) -+ return 0; -+ } - } - - return 1; -diff -Nur linux-2.6.30.orig/fs/jbd/commit.c linux-2.6.30/fs/jbd/commit.c ---- linux-2.6.30.orig/fs/jbd/commit.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/fs/jbd/commit.c 2009-06-14 20:25:20.000000000 +0200 -@@ -241,7 +241,7 @@ - spin_lock(&journal->j_list_lock); - } - /* Someone already cleaned up the buffer? */ -- if (!buffer_jbd(bh) || bh2jh(bh) != jh -+ if (!buffer_jbd(bh) - || jh->b_transaction != commit_transaction - || jh->b_jlist != BJ_SyncData) { - jbd_unlock_bh_state(bh); -@@ -478,9 +478,7 @@ - spin_lock(&journal->j_list_lock); - continue; - } -- if (buffer_jbd(bh) && bh2jh(bh) == jh && -- jh->b_transaction == commit_transaction && -- jh->b_jlist == BJ_Locked) { -+ if (buffer_jbd(bh) && jh->b_jlist == BJ_Locked) { - __journal_unfile_buffer(jh); - jbd_unlock_bh_state(bh); - journal_remove_journal_head(bh); -diff -Nur linux-2.6.30.orig/.gitignore linux-2.6.30/.gitignore ---- linux-2.6.30.orig/.gitignore 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/.gitignore 2009-06-14 20:25:19.000000000 +0200 -@@ -32,6 +32,7 @@ - tags - TAGS - vmlinux -+vmlinux.32 - System.map - Module.markers - Module.symvers -diff -Nur linux-2.6.30.orig/include/linux/cpumask.h linux-2.6.30/include/linux/cpumask.h ---- linux-2.6.30.orig/include/linux/cpumask.h 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/include/linux/cpumask.h 2009-06-14 20:25:20.000000000 +0200 -@@ -1022,8 +1022,6 @@ - - bool alloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node); - bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags); --bool zalloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node); --bool zalloc_cpumask_var(cpumask_var_t *mask, gfp_t flags); - void alloc_bootmem_cpumask_var(cpumask_var_t *mask); - void free_cpumask_var(cpumask_var_t mask); - void free_bootmem_cpumask_var(cpumask_var_t mask); -@@ -1042,19 +1040,6 @@ - return true; - } - --static inline bool zalloc_cpumask_var(cpumask_var_t *mask, gfp_t flags) --{ -- cpumask_clear(*mask); -- return true; --} -- --static inline bool zalloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, -- int node) --{ -- cpumask_clear(*mask); -- return true; --} -- - static inline void alloc_bootmem_cpumask_var(cpumask_var_t *mask) - { - } -diff -Nur linux-2.6.30.orig/ipc/shm.c linux-2.6.30/ipc/shm.c ---- linux-2.6.30.orig/ipc/shm.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/ipc/shm.c 2009-06-14 20:25:20.000000000 +0200 -@@ -969,13 +969,10 @@ - SYSCALL_DEFINE1(shmdt, char __user *, shmaddr) - { - struct mm_struct *mm = current->mm; -- struct vm_area_struct *vma; -+ struct vm_area_struct *vma, *next; - unsigned long addr = (unsigned long)shmaddr; -- int retval = -EINVAL; --#ifdef CONFIG_MMU - loff_t size = 0; -- struct vm_area_struct *next; --#endif -+ int retval = -EINVAL; - - if (addr & ~PAGE_MASK) - return retval; -diff -Nur linux-2.6.30.orig/kernel/sched_cpupri.c linux-2.6.30/kernel/sched_cpupri.c ---- linux-2.6.30.orig/kernel/sched_cpupri.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/kernel/sched_cpupri.c 2009-06-14 20:25:20.000000000 +0200 -@@ -165,7 +165,7 @@ - vec->count = 0; - if (bootmem) - alloc_bootmem_cpumask_var(&vec->mask); -- else if (!zalloc_cpumask_var(&vec->mask, GFP_KERNEL)) -+ else if (!alloc_cpumask_var(&vec->mask, GFP_KERNEL)) - goto cleanup; - } - -diff -Nur linux-2.6.30.orig/kernel/sched_rt.c linux-2.6.30/kernel/sched_rt.c ---- linux-2.6.30.orig/kernel/sched_rt.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/kernel/sched_rt.c 2009-06-14 20:25:20.000000000 +0200 -@@ -1591,7 +1591,7 @@ - unsigned int i; - - for_each_possible_cpu(i) -- zalloc_cpumask_var_node(&per_cpu(local_cpu_mask, i), -+ alloc_cpumask_var_node(&per_cpu(local_cpu_mask, i), - GFP_KERNEL, cpu_to_node(i)); - } - #endif /* CONFIG_SMP */ -diff -Nur linux-2.6.30.orig/kernel/smp.c linux-2.6.30/kernel/smp.c ---- linux-2.6.30.orig/kernel/smp.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/kernel/smp.c 2009-06-14 20:25:20.000000000 +0200 -@@ -52,7 +52,7 @@ - switch (action) { - case CPU_UP_PREPARE: - case CPU_UP_PREPARE_FROZEN: -- if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL, -+ if (!alloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL, - cpu_to_node(cpu))) - return NOTIFY_BAD; - break; -diff -Nur linux-2.6.30.orig/lib/cpumask.c linux-2.6.30/lib/cpumask.c ---- linux-2.6.30.orig/lib/cpumask.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/lib/cpumask.c 2009-06-14 20:25:20.000000000 +0200 -@@ -119,12 +119,6 @@ - } - EXPORT_SYMBOL(alloc_cpumask_var_node); - --bool zalloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node) --{ -- return alloc_cpumask_var_node(mask, flags | __GFP_ZERO, node); --} --EXPORT_SYMBOL(zalloc_cpumask_var_node); -- - /** - * alloc_cpumask_var - allocate a struct cpumask - * @mask: pointer to cpumask_var_t where the cpumask is returned -@@ -141,12 +135,6 @@ - } - EXPORT_SYMBOL(alloc_cpumask_var); - --bool zalloc_cpumask_var(cpumask_var_t *mask, gfp_t flags) --{ -- return alloc_cpumask_var(mask, flags | __GFP_ZERO); --} --EXPORT_SYMBOL(zalloc_cpumask_var); -- - /** - * alloc_bootmem_cpumask_var - allocate a struct cpumask from the bootmem arena. - * @mask: pointer to cpumask_var_t where the cpumask is returned -diff -Nur linux-2.6.30.orig/net/sched/cls_cgroup.c linux-2.6.30/net/sched/cls_cgroup.c ---- linux-2.6.30.orig/net/sched/cls_cgroup.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/net/sched/cls_cgroup.c 2009-06-14 20:25:20.000000000 +0200 -@@ -167,9 +167,6 @@ - struct tcf_exts e; - int err; - -- if (!tca[TCA_OPTIONS]) -- return -EINVAL; -- - if (head == NULL) { - if (!handle) - return -EINVAL; -diff -Nur linux-2.6.30.orig/sound/core/pcm_native.c linux-2.6.30/sound/core/pcm_native.c ---- linux-2.6.30.orig/sound/core/pcm_native.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/sound/core/pcm_native.c 2009-06-14 20:25:20.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/include/linux/fb.h linux-2.6.30.5/include/linux/fb.h +--- linux-2.6.30.5.orig/include/linux/fb.h 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/include/linux/fb.h 2009-08-22 11:50:27.000000000 +0200 +@@ -814,6 +814,7 @@ + int node; + int flags; + struct mutex lock; /* Lock for open/release/ioctl funcs */ ++ struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ + struct fb_var_screeninfo var; /* Current var */ + struct fb_fix_screeninfo fix; /* Current fix */ + struct fb_monspecs monspecs; /* Current Monitor specs */ +diff -Nur linux-2.6.30.5.orig/sound/core/pcm_native.c linux-2.6.30.5/sound/core/pcm_native.c +--- linux-2.6.30.5.orig/sound/core/pcm_native.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/sound/core/pcm_native.c 2009-08-21 21:18:15.000000000 +0200 @@ -3091,7 +3091,11 @@ return VM_FAULT_SIGBUS; } else { @@ -25130,9 +57890,9 @@ diff -Nur linux-2.6.30.orig/sound/core/pcm_native.c linux-2.6.30/sound/core/pcm_ offset = area->vm_pgoff << PAGE_SHIFT; switch (offset) { case SNDRV_PCM_MMAP_OFFSET_STATUS: -diff -Nur linux-2.6.30.orig/sound/core/sgbuf.c linux-2.6.30/sound/core/sgbuf.c ---- linux-2.6.30.orig/sound/core/sgbuf.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/sound/core/sgbuf.c 2009-06-14 20:25:20.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/sound/core/sgbuf.c linux-2.6.30.5/sound/core/sgbuf.c +--- linux-2.6.30.5.orig/sound/core/sgbuf.c 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/sound/core/sgbuf.c 2009-08-21 21:18:15.000000000 +0200 @@ -114,7 +114,11 @@ if (!i) table->addr |= chunk; /* mark head */ @@ -25158,9 +57918,9 @@ diff -Nur linux-2.6.30.orig/sound/core/sgbuf.c linux-2.6.30/sound/core/sgbuf.c if (! dmab->area) goto _failed; if (res_size) -diff -Nur linux-2.6.30.orig/sound/pci/Kconfig linux-2.6.30/sound/pci/Kconfig ---- linux-2.6.30.orig/sound/pci/Kconfig 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/sound/pci/Kconfig 2009-06-14 20:25:20.000000000 +0200 +diff -Nur linux-2.6.30.5.orig/sound/pci/Kconfig linux-2.6.30.5/sound/pci/Kconfig +--- linux-2.6.30.5.orig/sound/pci/Kconfig 2009-08-16 23:19:38.000000000 +0200 ++++ linux-2.6.30.5/sound/pci/Kconfig 2009-08-21 21:18:15.000000000 +0200 @@ -259,7 +259,6 @@ config SND_CS5535AUDIO @@ -25169,15 +57929,3 @@ diff -Nur linux-2.6.30.orig/sound/pci/Kconfig linux-2.6.30/sound/pci/Kconfig select SND_PCM select SND_AC97_CODEC help -diff -Nur linux-2.6.30.orig/virt/kvm/kvm_main.c linux-2.6.30/virt/kvm/kvm_main.c ---- linux-2.6.30.orig/virt/kvm/kvm_main.c 2009-06-10 05:05:27.000000000 +0200 -+++ linux-2.6.30/virt/kvm/kvm_main.c 2009-06-14 20:25:20.000000000 +0200 -@@ -2301,7 +2301,7 @@ - - bad_pfn = page_to_pfn(bad_page); - -- if (!zalloc_cpumask_var(&cpus_hardware_enabled, GFP_KERNEL)) { -+ if (!alloc_cpumask_var(&cpus_hardware_enabled, GFP_KERNEL)) { - r = -ENOMEM; - goto out_free_0; - } -- cgit v1.2.3